/****************************************************************************/
/*
* cwmp cms xml api.
*/
/****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <ctype.h>

#include "cms_common.h"
#include "cms_log.h"
#include "libmdm.h"
#include "cms_mdm.h"

#include "cmsXml_object.h"
#include "cmsXml_obj_id.h"
#include "cmsXml_oid_table.h"
#include "cmsXml_index_count.h"
#include "cms_alarm.h"
#include "cms_event.h"

extern OIDArray_t OIDTable[];

#if GC_APPS_CTC
	#define CWMP_EVENT_CODE_ALARM					"X CT-COM ALARM"
#elif GC_APPS_WASU
	#define CWMP_EVENT_CODE_ALARM					"X WASU ALARM"
#endif

/* get OID by prototype offset in cmsXml_obj_id.h. */
int cmsXml_GetOIDByTable( cmsoffset_t offset )
{
	int index = 0;
	while( OIDTable[ index ].offset )
	{
		if( OIDTable[ index ].offset == offset )
			return OIDTable[ index ].OID;

		index++;
	}
	return -1;
}

/* get prototype offset by OID in cmsXml_obj_id.h. */
cmsoffset_t cmsXml_GetOffsetByOID( int OID )
{
	if ( OID <= MAXOIDNUMBER )
	{
		return OIDTable[ OID ].offset;
	}
	return 0;
}


/* get fullpath by OID and IA in cmsXml_obj_id.h. */
void *cmsXml_GetFullpathByOIDIA( int OID, uint64_t objIA )
{
	char protoFullPath[256] = {0};
	int idxCnt = 0;
	char index[8] = {0};
	int i = 1;
	char *repFullPath = NULL;
	char *ptr = NULL;
	char *fullPath = NULL;

	if ( OID <= MAXOIDNUMBER ){
		fullPath = malloc(256);
		memset(fullPath, 0, 256);
		if(objIA == 0){
			strcpy(fullPath, OIDTable[ OID ].fullpath);
			return fullPath;
		}
		strcpy(protoFullPath, OIDTable[ OID ].fullpath);
		ptr = protoFullPath;
		idxCnt = cmsXmlGetIADepth(objIA);
		while(ptr){
			repFullPath = ptr;
			if((ptr = strstr(repFullPath, ".i"))== NULL){
				strcat(fullPath, repFullPath);
				break;
			}
			ptr++;
			*ptr = '\0';
			ptr++;
			strcat(fullPath, repFullPath);
			sprintf(index, "%d", cmsXmlGetIAInfo(objIA,i));
			strcat(fullPath, index);
			i++;
			if((ptr == NULL) || (*ptr == '\0')){
				break;
			}
			if(i > idxCnt){
				strcat(fullPath, ptr);
				break;
			}
		}
	}
	return fullPath;
}

/* get fullpath by OID in cmsXml_obj_id.h. */
void *cmsXml_GetFullPathByOID(int OID)
{
	char *fullPath = NULL;

	if ( OID <= MAXOIDNUMBER ){
		fullPath = malloc(256);
		memset(fullPath, 0, 256);
		
		strcpy(fullPath, OIDTable[ OID ].fullpath);
		return fullPath;
		
	}
		
	return fullPath;
}

/* get OID max in cmsXml_obj_id.h. */
int cmsXml_GetOIDMax(void)
{	
	return MAXOIDNUMBER;
}

char *cmsXml_encryptConf(void)
{  
	cmsXmlCb_t *xmlShmCb = NULL;
	void *object = NULL;
	static char provinceFile[128] = {0};
	static char defaultFile[128] = {0};
	static char configFile[128] = {0};
	int ret = -1;
	
	if( access(CMS_CUR_FILE_ENC, F_OK) == 0){
		CMS_LOG(LL_ERROR, "current xml is checking");
		ret = cmsXml_checkCurConfigCRC();
		if(ret == CMS_POK){
			if(access(CMS_BACKUP_CONFIG_FILE, F_OK) != 0){
				ret = CMS_OK;
			}
		}
		if(ret == CMS_OK){
			strcpy(configFile, CMS_CUR_FILE_ENC);
			CMS_LOG(LL_ERROR, "get current config file %s", configFile);
			return configFile;
		}
	}

	if( access(CMS_BACKUP_CONFIG_FILE, F_OK) == 0){
		CMS_LOG(LL_ERROR, "get backup config file %s\n", CMS_BACKUP_CONFIG_FILE);

		if(cmsXml_openSSL_Enc(CMS_BACKUP_CONFIG_FILE, "/tmp/config.curBak.enc") == CMS_OK){
			strcpy(configFile, "/tmp/config.curBak.enc");
			CMS_LOG(LL_ERROR, "get current backup config file %s",configFile);
			return configFile;
		}else{
			CMS_LOG(LL_ERROR, "enc xml fail after save!!!");
		}
	}

	if( access(CMS_PRE_CONFIG_FILE, F_OK) == 0){
		CMS_LOG(LL_ERROR, "get pre config file %s\n", CMS_PRE_CONFIG_FILE);
		
		if(cmsXml_openSSL_Enc(CMS_PRE_CONFIG_FILE, "/tmp/config.preDownload.enc") == CMS_OK){
			strcpy(configFile, "/tmp/config.preDownload.enc");
			CMS_LOG(LL_ERROR, "get pre partition default config file /tmp/config.preDownload.enc");
			return configFile;
		}else{
			CMS_LOG(LL_ERROR, "enc xml fail after save!!!");
		}
	}
	
	xmlShmCb = XMLSHMINIT();
	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xml shm init fail!!!");
		return NULL;
	}
	
	object = cmsXmlGetObjectByName(xmlShmCb, "InternetGatewayDevice.DeviceInfo");
	if(object != NULL){
		cmsObj_InternetGatewayDevice_DeviceInfo_t *deviceInfo = (cmsObj_InternetGatewayDevice_DeviceInfo_t *)object;
		snprintf(provinceFile, sizeof(provinceFile), "%s/CN_%s.default.enc", DEF_XML_PATH, deviceInfo->Province);
		CMS_LOG(LL_ERROR, "default provice config file %s", provinceFile);
		if( access(provinceFile, F_OK) == 0){
			CMS_LOG(LL_ERROR, "get province config file %s", provinceFile);
			XMLSHMDEINIT(xmlShmCb);
			return provinceFile; 
		}else{
			snprintf(defaultFile, sizeof(defaultFile) -1, "%s", CMS_DEF_FILE_ENC);
			CMS_LOG(LL_ERROR, "get default config file %s", defaultFile);
			XMLSHMDEINIT(xmlShmCb);
			return defaultFile;
		}
	}else{
		CMS_LOG(LL_ERROR, "get deviceinfo object fail!!!");
	}

	XMLSHMDEINIT(xmlShmCb);
	return NULL;
}



/*replace a character in string, c1 is old , c2 is new*/
static void cReplace(char *str, char *c1, char *c2)
{
	char *p;
	for( ; *str; str++) 
	{
		for(p=c1; *p && *p!=*str; p++);
		if(*p)
			*str = *(p-c1+c2);
	}
}

static uint32_t cmsXml_cmsTypeToCwmpType(uint32_t valueType)
{
	if(((valueType & PARAMETER_TYPE_STRING) == PARAMETER_TYPE_STRING) ||
		(valueType == PARAMETER_WRITE_IPV4) ||
		(valueType == PARAMETER_WRITE_IPV6) || 
		(valueType == PARAMETER_TYPE_MAC)){
		return CWMP_PARAM_TYPE_STRING;
	}else if(valueType == PARAMETER_TYPE_BOOLEAN){
		return CWMP_PARAM_TYPE_BOOLEAN;
	}else if((valueType & PARAMETER_TYPE_DATETIME) == PARAMETER_TYPE_DATETIME){
		return CWMP_PARAM_TYPE_DATATIME;
	}else if((valueType == PARAMETER_TYPE_UINT8) ||
		(valueType == PARAMETER_TYPE_UINT16) ||
		(valueType == PARAMETER_TYPE_UINT32) ||
		(valueType == PARAMETER_TYPE_UINT64)){
		return CWMP_PARAM_TYPE_UNSINGED_INT;
	}else if((valueType == PARAMETER_TYPE_SINT7) ||
		(valueType == PARAMETER_TYPE_SINT15) ||
		(valueType == PARAMETER_TYPE_SINT31) ||
		(valueType == PARAMETER_TYPE_SINT63)){
		return CWMP_PARAM_TYPE_INT;
	}else{
		CMS_LOG(LL_ERROR, "unknown valueType %d.\n", valueType);
		return CWMP_PARAM_TYPE_UNKNOWN;
	}
}



/*judge path is object path or object+parameter path,
-1 -- error, 0 -- object path, 1 -- object+parameter path
*/
static int isObjectOrParameter(
	const char *paraPathName, 
	char *objPathName, 
	char *objParameterName)
{
	uint32_t len = 0;
	int LocalRecord = 0, i = 0;
	
	if(paraPathName == NULL){
		CMS_LOG(LL_ERROR, "object&parameter path is NULL.\n");
		return -1;
	}

	len = strlen(paraPathName);
	if(paraPathName[len-1] == '.'){
		CMS_LOG(LL_SPEW, "object path.\n");
		if(objPathName != NULL){
			strncpy(objPathName, paraPathName, len-1);
		}else{
			CMS_LOG(LL_ERROR, "objPathName is NULL.\n");
			return -1;
		}
		return 0;
	}else{
		for(i = 0; i < strlen(paraPathName); i++){
			if(paraPathName[i] == '.')
				LocalRecord = i;
		}

		if((objPathName != NULL) && (objParameterName != NULL)){
			strcpy(objParameterName, &paraPathName[LocalRecord+1]);
			strncpy(objPathName, paraPathName, LocalRecord);
		}else{
			CMS_LOG(LL_ERROR, "objPathName or objParameterName is NULL.\n");
			return -1;
		}

		return 1;
	}

	return 0;
}


/*find parameter in object exist, exist - return 1; not exist -- return -1*/
static int cmsXml_checkParameterExist(
	cmsXmlCb_t *xmlShmCb, 
	cmsoffset_t objOff, 
	char *parameterName)
{
	void *object = NULL;
	objectNode_t *node = NULL;
	char *metaAddr = NULL;
	char *nodeAddr = NULL;
	char *meta_ptr = NULL;
	cmsoffset_t metaOffset = 0, nodeOffset = 0;
	int foundFlag = -1;  //1-found parameter, -1 -- not found
	
	object = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(objOff));
	
	/*use object to find the meta data*/
	metaAddr = object -sizeof(cmsoffset_t);
	metaOffset = *((cmsoffset_t *)metaAddr);

	/*use oid to find the object node*/
	nodeAddr = object -sizeof(cmsoffset_t)*2;
	nodeOffset = *((cmsoffset_t *)nodeAddr);
	node = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(nodeOffset));

	/*get parameter ptr*/
	meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(metaOffset));
		
	if(cmsXml_SearchParameter(xmlShmCb, node, parameterName, &meta_ptr) == CMS_OK)
		foundFlag = 1;

	return foundFlag;
}
#if 1
int updateAlarmNumber(cmsXmlCb_t *xmlShmCb, char *AlarmID, int addEvent)
{
 	int index = 0;
	int ret = 0;
	void *object = NULL;
	void *alarmList_object = NULL;
 	char objPathName[256] = {0};
	char buf[257] = {0};
	time_t curtime;
	int maxnumber=InternetGatewayDevice_DeviceInfo_X_CMCC_Alarm_AlarmList_i_Max;
	cmsObj_InternetGatewayDevice_DeviceInfo_X_CMCC_Alarm_t *Alarm_entry = NULL;
	cmsoffset_t objOff;
	int saveFlag = 1;
	
	if(xmlShmCb==NULL)
		return -1;
	CMS_LOG(LL_SPEW, "Enter updateAlarmNumber..\n");
	object = cmsXml_GetObjectByOID(xmlShmCb, OID_InternetGatewayDevice_DeviceInfo_X_CMCC_Alarm, 0, NULL_IF_NOT_EXISTED);
	if (!object) {
		return -1;
	}
	Alarm_entry = (cmsObj_InternetGatewayDevice_DeviceInfo_X_CMCC_Alarm_t *)object;
	if (!Alarm_entry) {
		return -1;
	}
	sleep(1);
	
	if(strcmp(AlarmID, ALARM_SYSTEM_REBOOT) == 0 ||strcmp(AlarmID, ALARM_CPU_HIGH) == 0 || strcmp(AlarmID, ALARM_PORT_NOT_AVAILABLE) == 0)
	{
		CMS_LOG(LL_SPEW, "Alarm=%s no need save!\n", AlarmID);
		saveFlag = 0;
	}
	for(index=1;index<=maxnumber;index++)
	{
		sprintf(objPathName, "InternetGatewayDevice.DeviceInfo.X_CMCC_Alarm.AlarmList.%d", index);
		alarmList_object = cmsXml_GetObjectByName(xmlShmCb, objPathName, NULL_IF_NOT_EXISTED);
		if (alarmList_object) {
			cmsObj_InternetGatewayDevice_DeviceInfo_X_CMCC_Alarm_AlarmList_i_t *AlarmList_p = (cmsObj_InternetGatewayDevice_DeviceInfo_X_CMCC_Alarm_AlarmList_i_t *)alarmList_object;
			CMS_LOG(LL_SPEW, "AlarmID: %s, AlarmTime: %u\n", AlarmList_p->AlarmID, AlarmList_p->AlarmTime);
			if(strlen(AlarmList_p->AlarmID) )
			{
				if(strlen(buf))
					strcat(buf, ",");
				strcat(buf, AlarmList_p->AlarmID);
			}
		}
	}
	CMS_LOG(LL_SPEW, "buf=%s\n", buf);
	if(strlen(buf) == 0)
		curtime = 0;
	else
		curtime = time(NULL);		
	objOff = cmsXmlGetPtrOffset(xmlShmCb, object);
	paraValueSettingList_t *paralist = newParameterList();
	setParameterToList(paralist, "AlarmNumber", PARAMETER_TYPE_STRING, buf);
	if(addEvent == 1)
		setParameterToList(paralist, "EventTime", PARAMETER_TYPE_UINT32, &curtime);
	cmsXmlSetParameterNnotify(xmlShmCb,objOff,paralist, FALSE);
	freeParameterList(paralist);
	if(saveFlag == 1)
		cmsXmlSave(xmlShmCb);
	return ret;
}

int updateAlarmTime(cmsXmlCb_t *xmlShmCb)
{
	int ret = 0;
	void *object = NULL;
	time_t curtime;
	cmsObj_InternetGatewayDevice_DeviceInfo_X_CMCC_Alarm_t *Alarm_entry = NULL;
	cmsoffset_t objOff;
	
	if(xmlShmCb==NULL)
		return -1;
	CMS_LOG(LL_SPEW, "Enter updateAlarmTime..\n");
	object = cmsXml_GetObjectByOID(xmlShmCb, OID_InternetGatewayDevice_DeviceInfo_X_CMCC_Alarm, 0, NULL_IF_NOT_EXISTED);
	if (!object) {
		return -1;
	}
	Alarm_entry = (cmsObj_InternetGatewayDevice_DeviceInfo_X_CMCC_Alarm_t *)object;
	if (!Alarm_entry) {
		return -1;
	}
	curtime = time(NULL);		
	objOff = cmsXmlGetPtrOffset(xmlShmCb, object);
	paraValueSettingList_t *paralist = newParameterList();
	setParameterToList(paralist, "EventTime", PARAMETER_TYPE_UINT32, &curtime);
	cmsXmlSetParameterNnotify(xmlShmCb,objOff,paralist, FALSE);
	freeParameterList(paralist);	
	return ret;
}

int AlarmList_AddIndex(cmsXmlCb_t *xmlShmCb, char *AlarmID){
	int index=0;
	uint64_t objIA;
	int addindex=-1;
	int exist = 0;
	void *object = NULL;
 	char objPathName[256] = {0};
	int maxnumber=InternetGatewayDevice_DeviceInfo_X_CMCC_Alarm_AlarmList_i_Max;
	time_t curtime;
	cmsoffset_t objOff;
	if(xmlShmCb==NULL)
		return -1;
	CMS_LOG(LL_SPEW, "Enter AlarmList_AddIndex, AlarmID is %s...\n", AlarmID);
	for(index=1;index<maxnumber;index++){
		sprintf(objPathName, "InternetGatewayDevice.DeviceInfo.X_CMCC_Alarm.AlarmList.%d", index);
		object = cmsXml_GetObjectByName(xmlShmCb, objPathName, NULL_IF_NOT_EXISTED);
		if (object) {
			cmsObj_InternetGatewayDevice_DeviceInfo_X_CMCC_Alarm_AlarmList_i_t *AlarmList_p = (cmsObj_InternetGatewayDevice_DeviceInfo_X_CMCC_Alarm_AlarmList_i_t *)object;
			if (strcmp(AlarmList_p->AlarmID, AlarmID) == 0) {
				CMS_LOG(LL_SPEW, "found AlarmID %s", AlarmID);
				exist = 1;
				objOff = cmsXmlGetPtrOffset(xmlShmCb, object);
				paraValueSettingList_t *paralist = newParameterList();
				curtime = time(NULL);
				setParameterToList(paralist, "AlarmTime", PARAMETER_TYPE_UINT32, &curtime);
				cmsXmlSetParameterNnotify(xmlShmCb,objOff,paralist, FALSE);
				freeParameterList(paralist);
			}
		}
	}
	if(exist == 1)
		return -1;
	for(index=0;index<maxnumber;index++){
		objIA = cmsXmlConstructIAValue(1, "%d",(index+1));
		object= cmsXml_GetObjectByOID(xmlShmCb, OID_InternetGatewayDevice_DeviceInfo_X_CMCC_Alarm_AlarmList_i,objIA,NULL_IF_NOT_EXISTED);
		if(object==NULL){
			addindex=index+1;
			break;
		}
	}
	return addindex;
}
#if defined(GC_APPS_CTC) ||defined(GC_APPS_WASU)
const struct ctc_alarmInfo_struct ctc_alarmInfo[] = {
	{ALARM_SYSTEM_REBOOT,						CTC_ALARM_REPORT_SYSLOG,					CTC_ALARM_MINOR},
	{ALARM_PORT_NOT_AVAILABLE,				CTC_ALARM_REPORT_SYSLOG, 				CTC_ALARM_CRITICAL},
	{ALARM_WLAN_HW_FAULT,						CTC_ALARM_REPORT_SYSLOG, 				CTC_ALARM_CRITICAL},
	{ALARM_WLAN_SW_FAULT,						CTC_ALARM_REPORT_SYSLOG, 				CTC_ALARM_CRITICAL},
	{ALARM_CPU_HIGH,							CTC_ALARM_REPORT_SYSLOG, 				CTC_ALARM_MAJOR},
	{ALARM_RAM_HIGH,							CTC_ALARM_REPORT_SYSLOG, 				CTC_ALARM_MAJOR},
	{ALARM_FILE_SERVER_UNREACHABLE,			CTC_ALARM_SYSLOG,							CTC_ALARM_CRITICAL},
	{ALARM_FILE_USER_ERROR,					CTC_ALARM_SYSLOG,							CTC_ALARM_CRITICAL},
	{ALARM_FILE_DOWNLOAD_TIMEOUT,				CTC_ALARM_SYSLOG,							CTC_ALARM_CRITICAL},
	{ALARM_FILE_NOT_FOUND,						CTC_ALARM_SYSLOG,							CTC_ALARM_CRITICAL},
	{ALARM_FILE_CONFIG_UPDATE_FAIL,					CTC_ALARM_SYSLOG,							CTC_ALARM_CRITICAL},
	{ALARM_FILE_BACKUP_FAIL,					CTC_ALARM_SYSLOG,							CTC_ALARM_CRITICAL},
	{ALARM_FILE_RESTORE_FAIL,					CTC_ALARM_SYSLOG,							CTC_ALARM_CRITICAL},
	{ALARM_FILE_CONFIG_FORMAT_ERROR,					CTC_ALARM_SYSLOG,							CTC_ALARM_CRITICAL},
	{ALARM_FILE_FIRMWARE_UPGRADE_FAIL,		CTC_ALARM_SYSLOG,							CTC_ALARM_CRITICAL},
	{ALARM_FLASH_INSUFFICIENT,					CTC_ALARM_SYSLOG,							CTC_ALARM_CRITICAL},
	{ALARM_SOFTWARE_UPGRADE_FAULT,			CTC_ALARM_SYSLOG,							CTC_ALARM_CRITICAL},
	{ALARM_SYSLOG_UPLOAD_FAIL,				CTC_ALARM_SYSLOG,							CTC_ALARM_CRITICAL},
	{ALARM_VoIP_NETWORK_UNREACHABLE,		CTC_ALARM_REPORT_SYSLOG,					CTC_ALARM_CRITICAL},
	{ALARM_VoIP_AUTH_FAIL, 						CTC_ALARM_REPORT_SYSLOG,					CTC_ALARM_CRITICAL},
	{ALARM_VoIP_REGISTER_FAIL, 					CTC_ALARM_REPORT_SYSLOG,					CTC_ALARM_CRITICAL},
	{ALARM_VoIP_REGISTER_NORESPONSE, 			CTC_ALARM_REPORT_SYSLOG,					CTC_ALARM_CRITICAL},
	{ALARM_PPPOE_DAIL_FAIL, 					CTC_ALARM_REPORT_SYSLOG,					CTC_ALARM_MAJOR},
	{ALARM_PPPOE_DAIL_SUCCESS, 				CTC_ALARM_REPORT_SYSLOG,					CTC_ALARM_MINOR},
	{ALARM_EPG_SERVER_UNREACHABLE,			CTC_ALARM_REPORT_SYSLOG,					CTC_ALARM_CRITICAL},
	{ALARM_DDNS_SERVER_UNREACHABLE,			CTC_ALARM_REPORT_SYSLOG,					CTC_ALARM_CRITICAL},
	{ALARM_DDNS_USER_ERROR, 					CTC_ALARM_REPORT_SYSLOG,					CTC_ALARM_CRITICAL},
};

int cms_store_event_code_to_file(char *event_code)
{
	char file_name[64] = {0};
	FILE *fp = NULL;
	
	CMS_LOG(LL_DEBUG, "event_code: %s\n", event_code);
	snprintf(file_name, sizeof(file_name) - 1, "/userconfig/config/cwmp_event");

	fp = fopen(file_name, "a+");
	if(fp == NULL){
		CMS_LOG(LL_ERROR, "open file %s failed.\n", file_name);
		return -1;
	}
	
	fprintf(fp, "%s#\n", event_code);
	fclose(fp);
	return 0;
}

static void send_alarmToRMS(char *alarm_code, int add)
{
	CMS_LOG(LL_DEBUG, "alarm_code: %s\n", alarm_code);
	if(strcmp(alarm_code, ALARM_SYSTEM_REBOOT) == 0)
	{
		cms_store_event_code_to_file(CWMP_EVENT_CODE_ALARM);
	}
	
	if(add == 1){ //add alarm
		if (cms_eventNotify(CMS_EVENT_CWMP_ALARM_REALTIME, PARAMETER_TYPE_STRING, alarm_code) < 0) {
		 	CMS_LOG(LL_ERROR, "cms send alarmNumber %s event to TR069 failed\r\n", alarm_code);
		}
	}
	else{ //del alarm
		if (cms_eventNotify(CMS_EVENT_CWMP_CLEAR_ALARM_REALTIME, PARAMETER_TYPE_STRING, alarm_code) < 0) {
			 CMS_LOG(LL_ERROR, "cms send clear alarmNumber %s event to TR069 failed\r\n", alarm_code);
		}

	}
}

int update_AlarmNumber(cmsXmlCb_t *xmlShmCb)
{
 	int index = 0;
	int ret = 0;
	void *object = NULL;
	void *alarmList_object = NULL;
 	char objPathName[256] = {0};
	char AlarmNumber[257] = {0};
	int maxnumber=InternetGatewayDevice_DeviceInfo_X_CT_COM_Alarm_AlarmList_i_Max;
	cmsObj_InternetGatewayDevice_DeviceInfo_X_CT_COM_Alarm_t *Alarm_entry = NULL;
	cmsoffset_t objOff;
	
	if(xmlShmCb==NULL)
		return -1;
	CMS_LOG(LL_DEBUG, "Enter updateAlarmNumber..\n");
	object = cmsXml_GetObjectByOID(xmlShmCb, OID_InternetGatewayDevice_DeviceInfo_X_CT_COM_Alarm, 0, NULL_IF_NOT_EXISTED);
	if (!object) {
		return -1;
	}
	Alarm_entry = (cmsObj_InternetGatewayDevice_DeviceInfo_X_CT_COM_Alarm_t *)object;
	if (!Alarm_entry) {
		return -1;
	}
	sleep(1);
	
	for(index=1;index<=maxnumber;index++)
	{
		sprintf(objPathName, "InternetGatewayDevice.DeviceInfo.X_CT-COM_Alarm.AlarmList.%d", index);
		alarmList_object = cmsXml_GetObjectByName(xmlShmCb, objPathName, NULL_IF_NOT_EXISTED);
		if (alarmList_object) {
			cmsObj_InternetGatewayDevice_DeviceInfo_X_CT_COM_Alarm_AlarmList_i_t *AlarmList_p = (cmsObj_InternetGatewayDevice_DeviceInfo_X_CT_COM_Alarm_AlarmList_i_t *)alarmList_object;
			if(strlen(AlarmList_p->AlarmCode) > 0)
			{
				if(strlen(AlarmNumber))
					strcat(AlarmNumber, ",");
				strcat(AlarmNumber, AlarmList_p->AlarmCode);
			}
		}
	}
	CMS_LOG(LL_DEBUG, "AlarmNumber=%s\n", AlarmNumber);
	objOff = cmsXmlGetPtrOffset(xmlShmCb, object);
	paraValueSettingList_t *paralist = newParameterList();
	setParameterToList(paralist, "AlarmNumber", PARAMETER_TYPE_STRING, AlarmNumber);
	cmsXmlSetParameterNnotify(xmlShmCb,objOff,paralist, FALSE);
	freeParameterList(paralist);
	return ret;
}

int AlarmList_addIndex(cmsXmlCb_t *xmlShmCb, char *alarm_code){
	int index=0;
	uint64_t objIA;
	int addindex=-1;
	int exist = 0;
	void *object = NULL;
 	char objPathName[256] = {0};
	int maxnumber=InternetGatewayDevice_DeviceInfo_X_CT_COM_Alarm_AlarmList_i_Max;
	
	if(xmlShmCb==NULL)
		return -1;
	CMS_LOG(LL_DEBUG, "Enter AlarmList_addIndex, AlarmID is %s.\n", alarm_code);
	for(index=1;index<maxnumber;index++){
		sprintf(objPathName, "InternetGatewayDevice.DeviceInfo.X_CT-COM_Alarm.AlarmList.%d", index);
		object = cmsXml_GetObjectByName(xmlShmCb, objPathName, NULL_IF_NOT_EXISTED);
		if (object) {
			cmsObj_InternetGatewayDevice_DeviceInfo_X_CT_COM_Alarm_AlarmList_i_t *AlarmList_p = (cmsObj_InternetGatewayDevice_DeviceInfo_X_CT_COM_Alarm_AlarmList_i_t *)object;
			if (strcmp(AlarmList_p->AlarmCode, alarm_code) == 0) {
				CMS_LOG(LL_DEBUG, "found AlarmCode %s", alarm_code);
				exist = 1;
			}
		}
	}
	if(exist == 1)
		return -1;
	for(index=0;index<maxnumber;index++){
		objIA = cmsXmlConstructIAValue(1, "%d",(index+1));
		object= cmsXml_GetObjectByOID(xmlShmCb, OID_InternetGatewayDevice_DeviceInfo_X_CT_COM_Alarm_AlarmList_i,objIA,NULL_IF_NOT_EXISTED);
		if(object==NULL){
			addindex=index+1;
			break;
		}
	}
	return addindex;
}

int cmsXml_del_AlarmID(char *alarm_code)
{
	cmsXmlCb_t *xmlShmCb = NULL;
 	int index = 0;
	int ret = 0;
	void *object = NULL;
 	char objPathName[256] = {0};
	int found = 0;
	int alarmScope = 0;
	
	xmlShmCb = XMLSHMINIT();
	if (xmlShmCb == NULL) {
		CMS_LOG(LL_ERROR, "xmlShm init error.\r\n");
		return -1;
	} else {
		CMS_LOG(LL_SPEW, "xmlShm init success.\r\n");
	}
	CMS_LOG(LL_DEBUG, "Enter cmsXml_del_AlarmID. alarm_code=%s\n", alarm_code);
	for (index = 1; index <= InternetGatewayDevice_DeviceInfo_X_CT_COM_Alarm_AlarmList_i_Max; index++) {
		sprintf(objPathName, "InternetGatewayDevice.DeviceInfo.X_CT-COM_Alarm.AlarmList.%d", index);
		object = cmsXml_GetObjectByName(xmlShmCb, objPathName, NULL_IF_NOT_EXISTED);
		if (object) {
			cmsObj_InternetGatewayDevice_DeviceInfo_X_CT_COM_Alarm_AlarmList_i_t *AlarmList_p = (cmsObj_InternetGatewayDevice_DeviceInfo_X_CT_COM_Alarm_AlarmList_i_t *)object;
			if (!strcmp(AlarmList_p->AlarmCode, alarm_code) || !strcmp(AlarmList_p->AlarmCode, "")) {
				if(!strcmp(AlarmList_p->AlarmCode, alarm_code))
					found = 1;
				alarmScope = AlarmList_p->AlarmScope; 
				cmsXmlDelObjByPathNameNnotify(xmlShmCb, objPathName, FALSE);
			}
		}
	}
	if(found){
		ret = update_AlarmNumber(xmlShmCb);
		if(alarmScope == 1 || alarmScope == 3)
			send_alarmToRMS(alarm_code, 0);
	}
	XMLSHMDEINIT(xmlShmCb);
	return ret;
}

 int cmsXml_add_AlarmID(char *alarm_code)
{
	cmsXmlCb_t *xmlShmCb = NULL;
	int alarm_oid=OID_InternetGatewayDevice_DeviceInfo_X_CT_COM_Alarm_AlarmList_i;
	void *object = NULL;
	uint32_t index=0;
	uint8_t severity = 0;
	uint8_t alarmScope = 0;
	int i = 0;
	
	cmsObj_InternetGatewayDevice_DeviceInfo_X_CT_COM_Alarm_t *Alarm_entry = NULL;
	
	xmlShmCb = XMLSHMINIT();
	if (xmlShmCb == NULL) {
		CMS_LOG(LL_ERROR, "xmlShm init error.\r\n");
		return -1;
	} else {
		CMS_LOG(LL_DEBUG, "xmlShm init success.\r\n");
	}
	object = cmsXml_GetObjectByOID(xmlShmCb, OID_InternetGatewayDevice_DeviceInfo_X_CT_COM_Alarm, 0, NULL_IF_NOT_EXISTED);
	if (!object) {
		goto finally;
	}
	Alarm_entry = (cmsObj_InternetGatewayDevice_DeviceInfo_X_CT_COM_Alarm_t *)object;
	if (Alarm_entry == NULL) {
		goto finally;
	}

	if(Alarm_entry->Enable == 0)
	{
		CMS_LOG(LL_DEBUG, "Alarm is disabled.\r\n");
		goto finally;
	}
	else{
		index=AlarmList_addIndex(xmlShmCb, alarm_code);
		if(index == -1)
		{
			goto finally;
		}
		for (i = 0; i < sizeof(ctc_alarmInfo) / sizeof(ctc_alarmInfo[0]); i++) {
			if (strcmp(ctc_alarmInfo[i].alarmCode, alarm_code) == 0)
			{
				severity = ctc_alarmInfo[i].alarmSeverity;
				alarmScope = ctc_alarmInfo[i].alarmScope;
				break;
			}
		}
		paraValueSettingList_t *paralist = newParameterList();
		setParameterToList(paralist, "AlarmCode", PARAMETER_TYPE_STRING, alarm_code);
		setParameterToList(paralist, "PerceivedSeverity", PARAMETER_TYPE_UINT8, &severity);
		setParameterToList(paralist, "AlarmScope", PARAMETER_TYPE_UINT8, &alarmScope);
		
		cmsXmlAddObjByOIDNnotify(xmlShmCb, alarm_oid,cmsXmlConstructIAValue(1,"%d",index), paralist, FALSE);
		freeParameterList(paralist);	
		update_AlarmNumber(xmlShmCb);
		if(alarmScope == 1 || alarmScope == 3)
			send_alarmToRMS(alarm_code, 1);
	}	
finally:
	XMLSHMDEINIT(xmlShmCb);
	return index;
}

#else
int cmsXml_del_AlarmID(char *AlarmID)

{
	cmsXmlCb_t *xmlShmCb = NULL;
 	int index = 0;
	int ret = 0;
	void *object = NULL;
 	char objPathName[256] = {0};
	int found = 0;
	
	xmlShmCb = XMLSHMINIT();
	if (xmlShmCb == NULL) {
		CMS_LOG(LL_ERROR, "xmlShm init error.\r\n");
		return -1;
	} else {
		CMS_LOG(LL_SPEW, "xmlShm init success.\r\n");
	}
	CMS_LOG(LL_SPEW, "Enter cmsXml_del_AlarmID. AlarmID=%s\n", AlarmID);
	for (index = 1; index <= InternetGatewayDevice_DeviceInfo_X_CMCC_Alarm_AlarmList_i_Max; index++) {
		sprintf(objPathName, "InternetGatewayDevice.DeviceInfo.X_CMCC_Alarm.AlarmList.%d", index);
		object = cmsXml_GetObjectByName(xmlShmCb, objPathName, NULL_IF_NOT_EXISTED);
		if (object) {
			cmsObj_InternetGatewayDevice_DeviceInfo_X_CMCC_Alarm_AlarmList_i_t *AlarmList_p = (cmsObj_InternetGatewayDevice_DeviceInfo_X_CMCC_Alarm_AlarmList_i_t *)object;
			if (!strcmp(AlarmList_p->AlarmID, AlarmID) || !strcmp(AlarmList_p->AlarmID, "")) {
				if(!strcmp(AlarmList_p->AlarmID, AlarmID))
					found = 1;
				CMS_LOG(LL_SPEW, "del obj, %s", objPathName);
				cmsXmlDelObjByPathNameNnotify(xmlShmCb, objPathName, FALSE);
			}
		}
	}
	if(found)
		ret = updateAlarmNumber(xmlShmCb, AlarmID, 0);
	
	XMLSHMDEINIT(xmlShmCb);
	return ret;
}
 
int cmsXml_add_AlarmID(char *AlarmID)

{
	cmsXmlCb_t *xmlShmCb = NULL;
	CMS_LOG(LL_SPEW, "Enter cmsXml_add_AlarmID...\n");
	int oper_oid=OID_InternetGatewayDevice_DeviceInfo_X_CMCC_Alarm_AlarmList_i;
	int index=0;
	time_t curtime;
	
	xmlShmCb = XMLSHMINIT();
	if (xmlShmCb == NULL) {
		CMS_LOG(LL_ERROR, "xmlShm init error.\r\n");
		return -1;
	} else {
		CMS_LOG(LL_SPEW, "xmlShm init success.\r\n");
	}
	
	index=AlarmList_AddIndex(xmlShmCb, AlarmID);
	if(index == -1)
	{
		updateAlarmTime(xmlShmCb);
		goto finally;
	}
	
	paraValueSettingList_t *paralist = newParameterList();
	curtime = time(NULL);
	CMS_LOG(LL_SPEW, "AlarmID=%s\n", AlarmID);
	setParameterToList(paralist, "AlarmID", PARAMETER_TYPE_STRING, AlarmID);
	setParameterToList(paralist, "AlarmTime", PARAMETER_TYPE_UINT32, &curtime);
	cmsXmlAddObjByOIDNnotify(xmlShmCb, oper_oid,cmsXmlConstructIAValue(1,"%d",index), paralist, FALSE);
	freeParameterList(paralist);	
	updateAlarmNumber(xmlShmCb, AlarmID, 1);
	
	finally:
		XMLSHMDEINIT(xmlShmCb);
		return index;
}
#endif
#endif

int cmsXml_save_faultcode(uint32_t fault_code, char *CommandKey, boolean needsave)
{
	cmsXmlCb_t *xmlShmCb = NULL;
	void *object=NULL;
	cmsoffset_t objOff;


	xmlShmCb = XMLSHMINIT();
	if (xmlShmCb == NULL) {
		CMS_LOG(LL_ERROR, "xmlShm init error.\r\n");
		return -1;
	} else {
		CMS_LOG(LL_SPEW, "xmlShm init success.\r\n");
	}
	
	object= cmsXml_GetObjectByOID(xmlShmCb, OID_InternetGatewayDevice_ManagementServer_TransferComplete,0,NULL_IF_NOT_EXISTED);
	if(object!=NULL){
		CMS_LOG(LL_INFO, " cwmp_save_DL_faultcode fault_code=%d,CommandKey=%s",fault_code,CommandKey);
		objOff = cmsXmlGetPtrOffset(xmlShmCb, object);

		paraValueSettingList_t *paralist = newParameterList();
		
		setParameterToList(paralist, "Faultcode", PARAMETER_TYPE_UINT32, &fault_code);
		if ( strlen(CommandKey) > 0 ){
			CMS_LOG(LL_INFO, " cwmp_save_DL_faultcode CommandKey=%s",CommandKey);
			setParameterToList(paralist, "CommandKey", PARAMETER_TYPE_STRING, CommandKey);
		}
		cmsXmlSetParameterByParaList(xmlShmCb,objOff,paralist);
		freeParameterList(paralist);
		if(needsave){
			cmsXmlSave(xmlShmCb);
		}
	}
	XMLSHMDEINIT(xmlShmCb);

	return 0;
}


#if 0
/*check paramter attr is readonly, 1 -- readonly; 0 -- writable*/
static uint32_t cmsXml_isParameterReadOnly(
	cmsXmlCb_t *xmlShmCb, 
	cmsoffset_t objOff, 
	char *parameterName)
{
	void *object = NULL;
	objectNode_t *node = NULL;
	char *metaAddr = NULL;
	char *nodeAddr = NULL;
	char *meta_ptr = NULL;
	cmsoffset_t metaOffset = 0, nodeOffset = 0, attrOffset = 0;
	uint8_t meta_len = 0;
	uint32_t attr = 0;
	int attrFlag = 1; // 1 -- readonly, 0 -- writable
	
	object = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(objOff));
	
	/*use object to find the meta data*/
	metaAddr = object -sizeof(cmsoffset_t);
	metaOffset = *((cmsoffset_t *)metaAddr);

	/*use oid to find the object node*/
	nodeAddr = object -sizeof(cmsoffset_t)*2;
	nodeOffset = *((cmsoffset_t *)nodeAddr);
	node = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(nodeOffset));

	/*get parameter ptr*/
	meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(metaOffset));
		
	if (cmsXml_SearchParameter(xmlShmCb, node, parameterName, &meta_ptr) == CMS_OK){

		meta_len = *((uint8_t *)meta_ptr);
	
		attrOffset = NTOHDL(*((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(cmsoffset_t)*1+sizeof(uint32_t)))));
		
		/*get parameter attribute*/
		attr = NTOHL(*((uint32_t *)(object+attrOffset)));
		
		if ((attr & PARAMETER_ATTR_READONLY) == PARAMETER_ATTR_READONLY){
			CMS_LOG(LL_ERROR, "The parameter attr is readonly!!!\n\r");
			attrFlag = 1;
		}else{
			attrFlag = 0;
		}
	}else{
		CMS_LOG(LL_ERROR, "The parameter is not exist in the object!!!\n\r");
		attrFlag = 1;
	}

	return attrFlag;
}
#endif

/*get paramter type, error == -1, ok -- 0*/
int cmsXml_getParameterType(
	cmsXmlCb_t *xmlShmCb, 
	cmsoffset_t objOff, 
	char *parameterName,
	uint32_t *type)
{
	void *object = NULL;
	objectNode_t *node = NULL;
	char *metaAddr = NULL;
	char *nodeAddr= NULL;
	char *meta_ptr = NULL;
	cmsoffset_t metaOffset = 0, nodeOffset = 0;
	uint32_t type_size = 0;
	uint8_t meta_len = 0;

	if(xmlShmCb == NULL)
		return -1;
	
	object = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(objOff));
	
	/*use object to find the meta data*/
	metaAddr = object -sizeof(cmsoffset_t);
	metaOffset = *((cmsoffset_t *)metaAddr);

	/*use oid to find the object node*/
	nodeAddr = object -sizeof(cmsoffset_t)*2;
	nodeOffset = *((cmsoffset_t *)nodeAddr);
	node = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(nodeOffset));

	/*get parameter ptr*/
	meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(metaOffset));
		
	if (cmsXml_SearchParameter(xmlShmCb, node, parameterName, &meta_ptr) == CMS_OK){

		meta_len = *((uint8_t *)meta_ptr);
		
		type_size = NTOHL(*((uint32_t *)(meta_ptr + meta_len - sizeof(uint32_t))));
	
			
		if ((type_size & PARAMETER_TYPE_STRING) == PARAMETER_TYPE_STRING){
			type_size = PARAMETER_TYPE_STRING;			
		}

		*type = type_size;
	}else{
		CMS_LOG(LL_ERROR, "The parameter is not exist in the object!!!\n\r");
		return -1;
	}
	
	return 0;
}

/*
	get parameter value range, error - return -1;  else return 0;
*/
int cmsXml_getParameterValueRange(
	cmsXmlCb_t *xmlShmCb, 
	cmsoffset_t objOff,
	char *parameterName,
	uint64_t *maxValue,
	int64_t *minValue)
{
	void *object = NULL;
	objectNode_t *node = NULL;
	char *metaAddr = NULL;
	char *nodeAddr = NULL;
	char *meta_ptr = NULL;
	cmsoffset_t metaOffset = 0, nodeOffset = 0;
	uint32_t size = 0, type_size = 0;
	uint8_t meta_len = 0;

	if(xmlShmCb == NULL)
		return -1;

	object = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(objOff));
	
	/*use object to find the meta data*/
	metaAddr = object -sizeof(cmsoffset_t);
	metaOffset = *((cmsoffset_t *)metaAddr);

	/*use oid to find the object node*/
	nodeAddr = object -sizeof(cmsoffset_t)*2;
	nodeOffset = *((cmsoffset_t *)nodeAddr);
	node = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(nodeOffset));

	/*get meta ptr*/
	meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(metaOffset));
		
	if (cmsXml_SearchParameter(xmlShmCb, node, parameterName, &meta_ptr) == CMS_OK){

		meta_len = *((uint8_t *)meta_ptr);
		
		type_size = NTOHL(*((uint32_t *)(meta_ptr + meta_len - sizeof(uint32_t))));
		
		if ((type_size & PARAMETER_TYPE_STRING) == PARAMETER_TYPE_STRING){
			size = type_size & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);
			type_size = PARAMETER_TYPE_STRING;	
		}
		
		switch(type_size){
			case PARAMETER_TYPE_BOOLEAN: 
				*maxValue = *((uint8_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
				*minValue = *((uint8_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
				break;
			case PARAMETER_TYPE_UINT8:
				*maxValue = *((uint8_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
				*minValue = *((uint8_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
				break;
			case PARAMETER_TYPE_UINT16:
				*maxValue = NTOHS(*((uint16_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
				*minValue = NTOHS(*((uint16_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
				break;
			case PARAMETER_TYPE_UINT32:
				*maxValue = NTOHL(*((uint32_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
				*minValue = NTOHL(*((uint32_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
				break;
			case PARAMETER_TYPE_UINT64:
				*maxValue = *((uint64_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
				*minValue = *((int64_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
				break;
			case PARAMETER_TYPE_SINT7:
				*maxValue = *((int8_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
				*minValue = *((int8_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
				break;
			case PARAMETER_TYPE_SINT15:
				*maxValue = NTOHS(*((int16_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
				*minValue = NTOHS(*((int16_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
				break;
			case PARAMETER_TYPE_SINT31:
				*maxValue = NTOHL(*((int32_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
				*minValue = NTOHL(*((int32_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2))));
				break;
			case PARAMETER_TYPE_SINT63:
				*maxValue = *((int64_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*2 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
				*minValue = *((int64_t *)(meta_ptr + meta_len - (sizeof(uint64_t)*1 + sizeof(uint32_t)*1 + sizeof(cmsoffset_t)*2)));
				break;
			case PARAMETER_TYPE_DATETIME:
				*maxValue = PARAMETER_TYPE_DATETIME;
				*minValue = 1;
				break;
			case PARAMETER_TYPE_STRING:
				*maxValue = size -1;
				*minValue = 1;
				break;
			default:
				CMS_LOG(LL_ERROR, " Parameter type is %d!!\n", type_size);
				break;
		}
		
		CMS_LOG(LL_DEBUG, "parameter %s, max range is "U64_", min is "S64_"\n",parameterName, *maxValue, *minValue);

	}else{
		return -1;
	}
		
	return 0;
}


/*
	Description: 
		cwmp set parameter value.
	Parameters:
		xmlShmCb -- share memory control block.	
 		paraPathName --  object full path name + parameter name.
 		value -- parameter value.
	return:										
		CMS_OK  -- success	
		CWMP_ERROR   -- fail
	For CWMP RPC SetParameterValues.
*/
int cmsXml_cwmpSetParameterValue(
	cmsXmlCb_t *xmlShmCb, 
	char *paraPathName, 
	void *value, 
	enum cwmp_parameterValue_type type,
	char *parameterKey)
{
	void *object = NULL;
	char objectPath[128] = {0};
	char parameterName[64] = {0};
	cmsoffset_t objOff;
	uint32_t valueType = 0;
	uint64_t maxValue = 0;
	int64_t  minValue = 0;
	uint32_t strLen = 0;
	int ret = -1;
	
	if((xmlShmCb == NULL)  || (paraPathName == NULL) || (value == NULL)){
		CMS_LOG(LL_ERROR, "error func parameter.\n");
		return CWMP_ERROR_INVALID_ARG;
	}

	/*set parameterKey*/
	if(parameterKey != NULL){
		if(strlen(parameterKey) > 32){
			CMS_LOG(LL_ERROR, "size of parameterkey exceeds the limit 32.\n");
			return CWMP_ERROR_INVALID_ARG;
		}

		object = cmsXml_GetObjectByName(xmlShmCb, "InternetGatewayDevice.ManagementServer", NULL_IF_NOT_EXISTED);
		if(object){
			objOff = cmsXmlGetPtrOffset(xmlShmCb, object);
			
			paraValueSettingList_t *paralist = newParameterList();
			
			setParameterToList(paralist, "ParameterKey", PARAMETER_TYPE_STRING, parameterKey);
			ret = cmsXmlSetParameterByParaList(xmlShmCb,objOff,paralist);
			if(ret == -1){
				CMS_LOG(LL_ERROR, "set ParameterKey fail.\n");
				return CWMP_ERROR_INTERNAL ;
			}
			freeParameterList(paralist);
		}else{
			CMS_LOG(LL_ERROR, "get ManagementServer fail.\n");
			return CWMP_ERROR_INTERNAL ;
		}
	}

	/*parse pathname to objectPath & parameter name*/
	if(isObjectOrParameter(paraPathName, objectPath, parameterName) != 1){
		CMS_LOG(LL_ERROR, "paraPathName is not object path+paramter name.\n");
		return CWMP_ERROR_INVALID_ARG;
	}

	if((strlen(parameterName) == 0) || (strlen(objectPath) == 0)){
		CMS_LOG(LL_ERROR, "object path or paramter is NULL.\n");
		return CWMP_ERROR_INVALID_ARG;
	}
	
	CMS_LOG(LL_INFO, "object path %s, para name %s\n", objectPath, parameterName);
	/*get object and set parameter value*/
	object = cmsXml_GetObjectByName(xmlShmCb, objectPath, NULL_IF_NOT_EXISTED);
	if(object){
		
		objOff = cmsXmlGetPtrOffset(xmlShmCb, object);
		if(cmsXml_checkParameterExist(xmlShmCb, objOff, parameterName) != 1){//can't found paramter in object
			CMS_LOG(LL_ERROR, "check parameter, it not exist.\n");
			return CWMP_ERROR_PARA_NAME;
		}

		/*if(cmsXml_isParameterReadOnly(xmlShmCb, objOff, parameterName) == 1){//readonly
			CMS_LOG(LL_ERROR, "check parameter, it readonly.\n");
			return CWMP_ERROR_SET_READONLY;
		}*/

		if(cmsXml_getParameterValueRange(xmlShmCb, objOff, parameterName, &maxValue, &minValue) != 0){//get value range
			CMS_LOG(LL_ERROR, "get parameter value range fail.\n");
			return CWMP_ERROR_INTERNAL ;
		}
		
		if(cmsXml_getParameterType(xmlShmCb, objOff, parameterName, &valueType) != 0){//get value type
			CMS_LOG(LL_ERROR, "get parameter value type fail.\n");
			return CWMP_ERROR_INTERNAL ;
		}
		
		CMS_LOG(LL_SPEW, "max range is "U64_", min is "S64_", valueType is 0x%x\n", maxValue, minValue, valueType);			
		switch(type){
			case CWMP_PARAM_TYPE_STRING:
				if((valueType & PARAMETER_TYPE_STRING) == PARAMETER_TYPE_STRING){
					if(strlen(value) > maxValue || strlen(value) < minValue){
						CMS_LOG(LL_ERROR, "set parameter value(%s) out of range.\n", (char *)value);
						return CWMP_ERROR_INVALID_VALUE;
					}
					paraValueSettingList_t *paralist = newParameterList();	
					setParameterToList(paralist, parameterName, valueType, value);
					ret = cmsXmlSetParameterByParaList(xmlShmCb, objOff, paralist);
					freeParameterList(paralist);

					if(ret == -1){
						CMS_LOG(LL_ERROR, "set parameter value fail.\n");
						return CWMP_ERROR_INTERNAL ;
					}
				}else{
					CMS_LOG(LL_ERROR, "erro value type, type in xml is 0x%x\n", valueType);
					return CWMP_ERROR_INVALID_TYPE;
				}
				break;
			case CWMP_PARAM_TYPE_INT:
				if(((valueType & PARAMETER_TYPE_SINT7) == PARAMETER_TYPE_SINT7) || 
					((valueType & PARAMETER_TYPE_SINT15) == PARAMETER_TYPE_SINT15) ||
					((valueType & PARAMETER_TYPE_SINT31) == PARAMETER_TYPE_SINT31)){
					if((atoi(value) > maxValue) || (atoi(value) < minValue)){
						CMS_LOG(LL_ERROR, "set parameter value(%d) out of range.\n", *(int32_t *)value);
						return CWMP_ERROR_INVALID_VALUE;
					}
					paraValueSettingList_t *paralist = newParameterList();
					int32_t paraValue = atoi(value);
					setParameterToList(paralist, parameterName, valueType, &paraValue);
					ret = cmsXmlSetParameterByParaList(xmlShmCb, objOff, paralist);
					freeParameterList(paralist);

					if(ret == -1){
						CMS_LOG(LL_ERROR, "set parameter value fail.\n");
						return CWMP_ERROR_INTERNAL ;
					}
				}else{
					CMS_LOG(LL_ERROR, "erro value type, type in xml is 0x%x\n", valueType);
					return CWMP_ERROR_INVALID_TYPE;
				}
				break;
			case CWMP_PARAM_TYPE_UNSINGED_INT:
				if(((valueType & PARAMETER_TYPE_UINT8) == PARAMETER_TYPE_UINT8) || 
					((valueType & PARAMETER_TYPE_UINT16) == PARAMETER_TYPE_UINT16) ||
					((valueType & PARAMETER_TYPE_UINT32) == PARAMETER_TYPE_UINT32)){
					if((strtoul(value,(char **)NULL, 10) > maxValue) || (strtoul(value,(char **)NULL, 10) < minValue)){
						CMS_LOG(LL_ERROR, "set parameter value(%lu) out of range.\n", strtoul(value,(char **)NULL, 10));
						return CWMP_ERROR_INVALID_VALUE;
					}
					paraValueSettingList_t *paralist = newParameterList();
					uint32_t paraValue = strtoul(value,(char **)NULL, 10);
					setParameterToList(paralist, parameterName, valueType, &paraValue);
					ret = cmsXmlSetParameterByParaList(xmlShmCb, objOff, paralist);
					freeParameterList(paralist);

					if(ret == -1){
						CMS_LOG(LL_ERROR, "set parameter value fail.\n");
						return CWMP_ERROR_INTERNAL ;
					}
				}else{
					CMS_LOG(LL_ERROR, "erro value type, type in xml is 0x%x\n", valueType);
					return CWMP_ERROR_INVALID_TYPE;
				}
				break;
			case CWMP_PARAM_TYPE_BOOLEAN:
				if((valueType & PARAMETER_TYPE_BOOLEAN) == PARAMETER_TYPE_BOOLEAN){
					if((atoi(value) != 0) && (atoi(value) != 1)){
						CMS_LOG(LL_ERROR, "set parameter value(%d) out of range.\n", *(int32_t *)value);
						return CWMP_ERROR_INVALID_VALUE;
					}
					paraValueSettingList_t *paralist = newParameterList();
					uint8_t paraValue = strtoul(value,(char **)NULL, 10);
					setParameterToList(paralist, parameterName, valueType, &paraValue);
					ret = cmsXmlSetParameterByParaList(xmlShmCb, objOff, paralist);
					freeParameterList(paralist);

					if(ret == -1){
						CMS_LOG(LL_ERROR, "set parameter value fail.\n");
						return CWMP_ERROR_INTERNAL ;
					}
				}else{
					CMS_LOG(LL_ERROR, "erro value type, type in xml is 0x%x\n", valueType);
					return CWMP_ERROR_INVALID_TYPE;
				}
				break;
			case CWMP_PARAM_TYPE_DATATIME:
				if((valueType & PARAMETER_TYPE_DATETIME) == PARAMETER_TYPE_DATETIME){
					strLen = strlen(value);
					if(strlen(value) > maxValue){
						CMS_LOG(LL_ERROR, "erro value %s, size(%u) exceed the max range(%d) \n", 
							(char *)value, strLen, PARAMETER_TYPE_DATETIME);
						return CWMP_ERROR_INVALID_VALUE;
					}
						
					paraValueSettingList_t *paralist = newParameterList();	
					setParameterToList(paralist, parameterName, valueType, value);
					ret = cmsXmlSetParameterByParaList(xmlShmCb, objOff, paralist);
					freeParameterList(paralist);

					if(ret == -1){
						CMS_LOG(LL_ERROR, "set parameter value fail.\n");
						return CWMP_ERROR_INTERNAL ;
					}
				}else{
					CMS_LOG(LL_ERROR, "erro value type, type in xml is 0x%x\n", valueType);
					return CWMP_ERROR_INVALID_TYPE;
				}
				break;
			case CWMP_PARAM_TYPE_BASE64:
				CMS_LOG(LL_ERROR, "current not support base64.\n");
				return CWMP_ERROR_INTERNAL ;
				break;
			default:
				CMS_LOG(LL_ERROR, "unknown value type %d\n", type);
				break;
		}
	}else{
		CMS_LOG(LL_ERROR, "get object by path name(%s) fail, parameter name is %s.\n", objectPath, parameterName);
		return CWMP_ERROR_INVALID_ARG;
	}

	return 0;
}


#if 1
int cmsXml_cwmpCheckParameterValue(
	cmsXmlCb_t *xmlShmCb, 
	void *object,
	cmsoffset_t objOff,
	char *parameterName, 
	uint32_t type,
	char *value)
{
	uint32_t valueType = 0;
	uint64_t maxValue = 0;
	int64_t  minValue = 0;
	uint32_t strLen = 0;
	char *cp;
	int is_minus = 0;

	if((xmlShmCb == NULL)  || (parameterName == NULL) || (value == NULL)){
		CMS_LOG(LL_ERROR, "error func parameter.\n");
		return CWMP_ERROR_INVALID_ARG;
	}

	if(object){
		if(cmsXml_checkParameterExist(xmlShmCb, objOff, parameterName) != 1){//can't found paramter in object
			CMS_LOG(LL_ERROR, "check parameter, it not exist.\n");
			return CWMP_ERROR_PARA_NAME;
		}

		if(cmsXml_getParameterValueRange(xmlShmCb, objOff, parameterName, &maxValue, &minValue) != 0){//get value range
			CMS_LOG(LL_ERROR, "get parameter value range fail.\n");
			return CWMP_ERROR_INTERNAL ;
		}
		
		if(cmsXml_getParameterType(xmlShmCb, objOff, parameterName, &valueType) != 0){//get value type
			CMS_LOG(LL_ERROR, "get parameter value type fail.\n");
			return CWMP_ERROR_INTERNAL ;
		}
		
		CMS_LOG(LL_SPEW, "max range is "U64_", min is "S64_", valueType is 0x%x\n", maxValue, minValue, valueType);	
		switch(type){
			case PARAMETER_TYPE_STRING:
				if((valueType & PARAMETER_TYPE_STRING) == PARAMETER_TYPE_STRING){
					if(strlen(value) > maxValue || strlen(value) < minValue){
						CMS_LOG(LL_ERROR, "set parameter value(%s) out of range.\n", (char *)value);
						return CWMP_ERROR_INVALID_VALUE;
					}
				}
				break;
			case PARAMETER_TYPE_SINT7:
			case PARAMETER_TYPE_SINT15:
				 if(((valueType & PARAMETER_TYPE_SINT7) == PARAMETER_TYPE_SINT7)||
				 	((valueType & PARAMETER_TYPE_SINT15) == PARAMETER_TYPE_SINT15)){
				
					for ( cp = value; *cp != '\0'; cp++ ){
						if(*cp == '-'){
							cp++;
						}
						if(!isdigit(*cp)){
							return CWMP_ERROR_INVALID_VALUE;
						}
					}
					if(((int32_t)atoi(value) > (int32_t)maxValue) || ((int32_t)atoi(value) < (int32_t)minValue)){
						CMS_LOG(LL_ERROR, "set parameter value(%d) out of range.\n", *(int32_t *)value);
						return CWMP_ERROR_INVALID_VALUE;
					}
				}
			 	break;
			 case PARAMETER_TYPE_SINT31:
				  if((valueType & PARAMETER_TYPE_SINT31) == PARAMETER_TYPE_SINT31){
					for ( cp = value; *cp != '\0'; cp++ ){
						if(*cp == '-'){
							is_minus = 1;
							cp++;
						}
						if(!isdigit(*cp)){
							return CWMP_ERROR_INVALID_VALUE;
						}
					}
					if(is_minus){
						if(((int32_t)atoi(value) > (int32_t)maxValue) || ((int32_t)atoi(value) < (int32_t)minValue)){
							CMS_LOG(LL_ERROR, "set parameter value(%d) out of range.\n", *(int32_t *)value);
							return CWMP_ERROR_INVALID_VALUE;
						}
					}else{
						if((strtoul(value,(char **)NULL, 10) > maxValue) || (strtoul(value,(char **)NULL, 10) < minValue)){
							CMS_LOG(LL_ERROR, "set parameter value(%d) out of range.\n", *(int32_t *)value);
							return CWMP_ERROR_INVALID_VALUE;
						}
					}
				 }
				break;
				case PARAMETER_TYPE_UINT8:
				case PARAMETER_TYPE_UINT16:
				case PARAMETER_TYPE_UINT32:
				   if(((valueType & PARAMETER_TYPE_UINT8) == PARAMETER_TYPE_UINT8) || 
					((valueType & PARAMETER_TYPE_UINT16) == PARAMETER_TYPE_UINT16) ||
					((valueType & PARAMETER_TYPE_UINT32) == PARAMETER_TYPE_UINT32)){
						for ( cp = value; *cp != '\0'; cp++ ){
							if(!isdigit(*cp)){
								return CWMP_ERROR_INVALID_VALUE;
							}
						}	
						if((strtoull(value,(char **)NULL, 10) > maxValue) || (strtoull(value,(char **)NULL, 10) < minValue)){
							CMS_LOG(LL_ERROR, "set parameter value(%lu) out of range.\n", strtoul(value,(char **)NULL, 10));
							return CWMP_ERROR_INVALID_VALUE;
						}
					}
				    break;
				case PARAMETER_TYPE_BOOLEAN:
					if((valueType & PARAMETER_TYPE_BOOLEAN) == PARAMETER_TYPE_BOOLEAN){
						if((atoi(value) != 0) && (atoi(value) != 1)){
							CMS_LOG(LL_ERROR, "set parameter value(%d) out of range.\n", *(int32_t *)value);
							return CWMP_ERROR_INVALID_VALUE;
						}
					}
				break;
				case PARAMETER_TYPE_DATETIME:
					 if((valueType & PARAMETER_TYPE_DATETIME) == PARAMETER_TYPE_DATETIME){
						strLen = strlen(value);
						if(strlen(value) > maxValue){
							CMS_LOG(LL_ERROR, "erro value %s, size(%u) exceed the max range(%d) \n", 
								(char *)value, strLen, PARAMETER_TYPE_DATETIME);
							return CWMP_ERROR_INVALID_VALUE;
						}						
					}
				 break;
				default:
				 {
					CMS_LOG(LL_ERROR, "get parameter name(%s) fail.\n", parameterName);
					return CWMP_ERROR_INVALID_VALUE;
				 }
		}
	}
	return 0;
}
#endif

static int getObjParaValues(
	cmsXmlCb_t *xmlShmCb,
	char *objPath,
	char *parameterName,
	paraValueSettingList_t **parameterList)
{
	paraValueSettingList_t *pCurParaList = NULL;
	void *objPtr = NULL;
	void **objParameters = NULL;
	cmsoffset_t objOffset = 0;
	
	uint32_t type_size = 0;
	uintptr_t *parameter = NULL;
	char **temp = NULL;
	parameterValue_t *value, *ptr;
	int foundFlag = 0;
	int i = 0;

	if(objPath == NULL)
		return -1;
	
	objPtr = cmsXml_GetObjectByName(xmlShmCb, objPath,  NULL_IF_NOT_EXISTED);
	if(objPtr == NULL){
		CMS_LOG(LL_ERROR, "get object %s fail.\n", objPath);
		return -1;
	}
	
	objOffset = cmsXmlGetPtrOffset(xmlShmCb, objPtr);
		
	objParameters = cmsXml_GetParameterNameByObjectName(xmlShmCb, objPath);
	if(objParameters){
		for(i = 0; i < xmlShmCb->meta_count; i++){
			//printf("parameter name is %s\n", (char *)*(objParameter+i));
			if(parameterName != NULL){
				if(strcmp(parameterName, *(objParameters+i)) == 0){
					foundFlag = 1;
				}else	
					continue;
			}
			
			parameter = malloc(sizeof(void*)*1);
			temp = (char **)parameter;
			*parameter = (uintptr_t )(*(objParameters+i));
			value = cmsXml_getParameter(xmlShmCb, objOffset, 1, temp);
			ptr = value;

			if(*parameterList == NULL){
				*parameterList = (paraValueSettingList_t *)calloc(1, sizeof(paraValueSettingList_t));
				sprintf((*parameterList)->parameter,  "%s.%s", objPath, (char *)*(objParameters+i));
				(*parameterList)->type = cmsXml_cmsTypeToCwmpType(ptr->type_size);
				
				if ((ptr->type_size & PARAMETER_TYPE_STRING) == PARAMETER_TYPE_STRING){
					type_size = strlen(ptr->value) + 1;

				}else{
					type_size = (ptr->type_size) & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);
				}

				(*parameterList)->value = (uint8_t *)calloc(type_size, sizeof(uint8_t));
				if((*parameterList)->value == NULL){
					CMS_LOG(LL_ERROR, "calloc parameter list value fail.\n");
					free(*parameterList);
					return -1;
				}

				memcpy((*parameterList)->value, ptr->value, type_size);
				
			}else{
				pCurParaList = (paraValueSettingList_t *)calloc(1, sizeof(paraValueSettingList_t));

				sprintf(pCurParaList->parameter,  "%s.%s", objPath, (char *)*(objParameters+i));
				pCurParaList->type = cmsXml_cmsTypeToCwmpType(ptr->type_size);
				
				if ((ptr->type_size & PARAMETER_TYPE_STRING) == PARAMETER_TYPE_STRING){
					type_size = strlen(ptr->value) + 1;

				}else{
					type_size = (ptr->type_size) & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);
				}

				pCurParaList->value = (uint8_t *)calloc(type_size, sizeof(uint8_t));
				if(pCurParaList->value == NULL){
					CMS_LOG(LL_ERROR, "calloc parameter list value fail.\n");
					free(pCurParaList);
					return -1;
				}

				memcpy(pCurParaList->value, ptr->value, type_size);

				INSERT_NODE((*parameterList), pCurParaList);
			}

			
			free(temp);
			cmsXml_freeParameterBuffer(value, 1); /*must free after get parameter*/

			if(foundFlag == 1)
				break;
		}
		
		cmsXml_freeParameterNameBuffer(objParameters);
	}else{
		return -1;
	}

	if((parameterName != NULL) && (foundFlag == 0))
		return -1;
	
	return 0;
}

/*
	Description: 
		cwmp get parameter value by full path name. 
		such as: InternetGateWayDevice.Device.SerialNumber or InternetGateWayDevice.Device.
		full path name, get one parameter value; end with ".", get all parameter value of this object.
	Parameters:
		xmlShmCb -- share memory control block.	
 		paraPathName --  object full path name.
 		parameterList -- object parameter value list.
	return:										
		CMS_OK  -- success	
		CWMP_ERROR   -- fail
	For CWMP RPC GetParameterValues.
*/
int cmsXml_cwmpGetParameterValue(
	cmsXmlCb_t *xmlShmCb, 
	char *paraPathName,
	paraValueSettingList_t **parameterList)
{
	//objectList_t *pCurObj = NULL, *objChildList = NULL;
	void *object = NULL;
	//char *objPathName = NULL;
	char objectPath[128] = {0};
	char parameterName[64] = {0};
	int ret = -1;
	int getRet = -1;
	
	if((xmlShmCb == NULL) || (paraPathName == NULL)){
		CMS_LOG(LL_ERROR, "func para is NULL.\n");
		return CWMP_ERROR_REQ_DENIED;
	}

	//paraPathName is NULL, get all paramter value
	/*if(paraPathName == NULL){
		object = cmsXml_GetObjectByName(xmlShmCb,"InternetGatewayDevice", NULL_IF_NOT_EXISTED);
		if(object){
			pCurObj = cmsXml_GetObjListByName(xmlShmCb, "InternetGatewayDevice");
			objPathName = cmsXml_GetFullpathByOIDIA(pCurObj->OID, pCurObj->IA);
			getObjParaValues(xmlShmCb, objPathName, NULL, parameterList);
			free(objPathName);
			
			objChildList = cmsXml_GetFullChildList(xmlShmCb, pCurObj->OID, pCurObj->IA);
			cmsXml_FreeObjList(&pCurObj);
			while(objChildList){
				objPathName = cmsXml_GetFullpathByOIDIA(objChildList->OID, objChildList->IA);
				getObjParaValues(xmlShmCb, objPathName, NULL, parameterList);
				free(objPathName);
				objChildList = objChildList->next;
			}
			if(objChildList)
				cmsXml_FreeObjList(&objChildList);
		}else{
			CMS_LOG(LL_ERROR, "get object InternetGatewayDevice fail.\n");
			return CWMP_ERROR_INTERNAL;
		}

		return CWMP_OK;
	}
	*/

	ret = isObjectOrParameter(paraPathName, objectPath, parameterName);
	if(ret == -1){
		CMS_LOG(LL_ERROR, "paraPathName is not object path or paramter name.\n");
		return CWMP_ERROR_INVALID_ARG;
	}else if(ret == 0){//object, end with '.'
		object = cmsXml_GetObjectByName(xmlShmCb, objectPath,  NULL_IF_NOT_EXISTED);
		if(object){
			getRet = getObjParaValues(xmlShmCb, objectPath, NULL, parameterList);
			if(getRet == -1){
				CMS_LOG(LL_ERROR, "get object %s paramter values fail.\n", objectPath);
				return CWMP_ERROR_INTERNAL;
			}
			/*pCurObj = cmsXml_GetObjListByName(xmlShmCb, objectPath);
			if(pCurObj){	
				objChildList = cmsXml_GetFullChildList(xmlShmCb, pCurObj->OID, pCurObj->IA);

				while(objChildList){
					objPathName = cmsXml_GetFullpathByOIDIA(objChildList->OID, objChildList->IA);
					getObjParaValues(xmlShmCb, objPathName, NULL, parameterList);
					free(objPathName);
					objChildList = objChildList->next;
				}
				cmsXml_FreeObjList(&pCurObj);
			}*/
		}else
			return CWMP_ERROR_INVALID_ARG;
	}else if(ret == 1){//parameter, end with parameter name
		getRet = getObjParaValues(xmlShmCb, objectPath, parameterName, parameterList);
		if(getRet == -1){
			CMS_LOG(LL_ERROR, "can't found parameter %s\n", parameterName);
			return CWMP_ERROR_INVALID_ARG;
		}
	}else{
		return CWMP_ERROR_INVALID_ARG;
	}

	return CWMP_OK;
}

/*
	Description: 
		free parameter info list. 
	Parameters:
 		parameterList -- object parameter value list.
	return:										
		NULL
		
*/
void cmsXml_cwmpFreeParameterValue(paraValueSettingList_t *parameterList)
{
	paraValueSettingList_t *pCurParaList = NULL, *tmpParaList = NULL;

	pCurParaList = parameterList;
	while(pCurParaList){
		tmpParaList = pCurParaList;
		pCurParaList = pCurParaList->next;

		free(tmpParaList->value);
		DELETE_NODE(parameterList, tmpParaList);
	}
	
}

static int getSpotNum(const char *pathName)
{
	int len = 0;
	int i = 0;
	int count = 0;

	if(pathName == NULL)
		return count;

	len = strlen(pathName);

	for(i = 0; i < len; i++){
		if(pathName[i] == '.')
			count++;
	}

	return count;
}

static int getObjParaNames(
	cmsXmlCb_t *xmlShmCb,
	char *objPath,
	boolean nextLevel,
	cwmp_getObjParaList_t **objParaList)
{
	void *objPtr = NULL;
	void **objParameters = NULL;
	cmsoffset_t objOffset = 0;
	uint32_t attrFlag = 0;
	int i = 0;

	if(objPath == NULL)
		return -1;

	if(nextLevel == false){
		objPtr = cmsXml_GetObjectByName(xmlShmCb, objPath,  NULL_IF_NOT_EXISTED);
		if(objPtr == NULL){
			CMS_LOG(LL_ERROR, "get object %s fail.\n", objPath);
			return -1;
		}
		
		objOffset = cmsXmlGetPtrOffset(xmlShmCb, objPtr);
			
		objParameters = cmsXml_GetParameterNameByObjectName(xmlShmCb, objPath);
		if(objParameters){
			for(i = 0; i < xmlShmCb->meta_count; i++){
				
				attrFlag = cmsXml_getParameterAttr(xmlShmCb, objOffset, *(objParameters+i));

				if(*objParaList == NULL){
					*objParaList = (cwmp_getObjParaList_t *)calloc(1, sizeof(cwmp_getObjParaList_t));
					sprintf((*objParaList)->parameterPath, "%s.%s", objPath, (char *)(*(objParameters+i)));
					(*objParaList)->writeable = (((attrFlag & PARAMETER_ATTR_READONLY) == PARAMETER_ATTR_READONLY) ? false : true);
				}else{
					cwmp_getObjParaList_t *curObjPara = (cwmp_getObjParaList_t *)calloc(1, sizeof(cwmp_getObjParaList_t));
					sprintf(curObjPara->parameterPath, "%s.%s", objPath, (char *)(*(objParameters+i)));
					curObjPara->writeable = (((attrFlag & PARAMETER_ATTR_READONLY) == PARAMETER_ATTR_READONLY) ? false : true);
					INSERT_NODE((*objParaList), curObjPara);
				}

			}
			
			cmsXml_freeParameterNameBuffer(objParameters);
		}else{
			return -1;
		}
	}else{

	}

	return 0;
}


/*****************************************************************
 *cmsXml_getObjParaList -- get the object full path name and 
 *						   object parameter name, and it's is 
 *						   writable or not.
 *
 *INPUT: xmlShmCb --  xml share memory block. 
 *		 objPath 	--	NULL, return all parameter of xml;
 						end with '.', return all parameter of the object;
 						end with parameter name, return the parameter info.
 *		 nextLevel	--  false,get all child object path name
 *						(end with ".")
 *						and parameter name; true, only get all 
 *						child objct path name(end with ".").
 *		objParaList -- parameter list cwmp get
 *OUTPUT: CWMP ERROR -- fail
 *        cwmp_getObjParaList_t type list -- success
 *
 *History:
 *	06/17/2020 cms:created
 * For CWMP RPC GetParameterName.
=================================================================*/
int cmsXml_cwmpGetObjParaList(
	cmsXmlCb_t *xmlShmCb, 
	char *objPath, 
	boolean nextLevel,
	cwmp_getObjParaList_t **objParaList)
{
	objectList_t *pCurObj = NULL, *objChildList = NULL;
	void *object = NULL;
	void **paraNameList = NULL;
	char *objPathName = NULL;
	char pathName[256] = {0};
	char parameterName[64] = {0};
	uint32_t objOff = 0, attrFlag = 0;
	int i = 0;
	int ret = -1;
	void **objParameter = NULL;
	int foundFlag = 0;
	*objParaList = NULL;
	
	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "func parameter is NULL.\n");
		return CWMP_ERROR_INVALID_ARG;
	}

	#if 0
	if(objPath == NULL){//get all xml parameter name
	
		object = cmsXml_GetObjectByName(xmlShmCb,"InternetGatewayDevice", NULL_IF_NOT_EXISTED);
		if(object){
			pCurObj = cmsXml_GetObjListByName(xmlShmCb, "InternetGatewayDevice");
			objPathName = cmsXml_GetFullpathByOIDIA(pCurObj->OID, pCurObj->IA);
			getObjParaNames(xmlShmCb, objPathName, false, objParaList);
			free(objPathName);
			
			objChildList = cmsXml_GetFullChildList(xmlShmCb, pCurObj->OID, pCurObj->IA);
			cmsXml_FreeObjList(&pCurObj);
			while(objChildList){
				objPathName = cmsXml_GetFullpathByOIDIA(objChildList->OID, objChildList->IA);
				getObjParaNames(xmlShmCb, objPathName, false, objParaList);
				free(objPathName);
				objChildList = objChildList->next;
			}
			if(objChildList)
				cmsXml_FreeObjList(&objChildList);
		}else{
			CMS_LOG(LL_ERROR, "get object InternetGatewayDevice fail.\n");
			return CWMP_ERROR_INTERNAL;
		}
		
	}else{
	#endif
	/*parse pathname to objectPath & parameter name*/
	ret = isObjectOrParameter(objPath, pathName, parameterName);
	if(ret == -1){//error
		CMS_LOG(LL_ERROR, "objPath is not object path+paramter name.\n");
		return CWMP_ERROR_INVALID_ARG;
	}else if(ret == 0){//object part path, end with '.'
		/*get child object info*/
		getObjParaNames(xmlShmCb, pathName, nextLevel, objParaList);
		object = cmsXml_GetObjectByName(xmlShmCb, pathName, NULL_IF_NOT_EXISTED);
		if(object){
			pCurObj = cmsXml_GetObjListByName(xmlShmCb, pathName);

			if(NULL != pCurObj){
				objChildList = cmsXml_GetFullChildList(xmlShmCb, pCurObj->OID, pCurObj->IA);
				cmsXml_FreeObjList(&pCurObj);
			}
			while(objChildList){
				objPathName = cmsXml_GetFullpathByOIDIA(objChildList->OID, objChildList->IA);
				if((nextLevel == true) && (getSpotNum(objPathName) != (getSpotNum(pathName)+1))){
					free(objPathName);
					continue;
				}
				
				getObjParaNames(xmlShmCb, objPathName, nextLevel, objParaList);
				free(objPathName);
				objChildList = objChildList->next;
			}
			if(objChildList)
				cmsXml_FreeObjList(&objChildList);
		}else{
			CMS_LOG(LL_ERROR, "get object InternetGatewayDevice fail.\n");
			return CWMP_ERROR_INTERNAL;
		}

	}else if(ret == 1){//complete path, end with parameterName
			
		objParameter = cmsXml_GetParameterNameByObjectName(xmlShmCb, pathName);
		if(objParameter){
			for(i = 0; i < xmlShmCb->meta_count; i++){
				if(!strcmp(parameterName, (char *)*(objParameter+i))){
					attrFlag = cmsXml_getParameterAttr(xmlShmCb, objOff, *(paraNameList+i));
					cwmp_getObjParaList_t *curObjPara = (cwmp_getObjParaList_t *)calloc(1, sizeof(cwmp_getObjParaList_t));
					strcpy(curObjPara->parameterPath, objPath);
					curObjPara->writeable = (((attrFlag & PARAMETER_ATTR_READONLY) == PARAMETER_ATTR_READONLY) ? false : true);

					*objParaList = curObjPara;
					foundFlag = 1;
					break;
				}
			}
			cmsXml_freeParameterNameBuffer(objParameter);

			if(foundFlag == 0){
				CMS_LOG(LL_ERROR,"object %s have no parameter %s.(%s)\n", pathName,parameterName, objPath);
				return CWMP_ERROR_PARA_NAME;
			}
		}else{
			CMS_LOG(LL_ERROR,"get object parameter list fail.(%s/%s/%s)\n",objPath, pathName,parameterName);
			return CWMP_ERROR_INTERNAL ;
		}
	}
	//}

	return CWMP_OK;
}

/*
	Description: 
		free object parameter info list. 
	Parameters:
 		objParaList -- object parameter list.
	return:										
		NULL
		
*/
int	cmsXml_cwmpFreeObjParaList(cwmp_getObjParaList_t *objParaList)
{
	cwmp_getObjParaList_t *curObjPara = NULL, *tmpObjPara = NULL;

	if(objParaList == NULL){
		CMS_LOG(LL_ERROR, "objPara list is NULL.\n");
		return -1;
	}

	curObjPara = objParaList;
	while(curObjPara){
		tmpObjPara = curObjPara;
		curObjPara = curObjPara->next;
		
		DELETE_NODE(objParaList,tmpObjPara);
	}

	return 0;
}
#if 0
int cms_cwmpDelEventFromXml(
	cmsXmlCb_t *xmlShmCb,
	char *event_code)

{
 	int event_index = 0;
	void *object = NULL;
 	char objPathName[256] = {0};
	
	if(xmlShmCb==NULL)
		return -1;
	CMS_LOG(LL_ERROR, "Enter cms_cwmpDelEventFromXml. event_code=%s\n", event_code);
	for (event_index = 1; event_index <= InternetGatewayDevice_EventStruct_i_Max; event_index++) {
		sprintf(objPathName, "InternetGatewayDevice.EventStruct.%d", event_index);
		object = cmsXml_GetObjectByName(xmlShmCb, objPathName, NULL_IF_NOT_EXISTED);
		if (object) {
			cmsObj_InternetGatewayDevice_EventStruct_i_t *event_struct = (cmsObj_InternetGatewayDevice_EventStruct_i_t *)object;
			CMS_LOG(LL_ERROR, "event_code: %s, command_key: %s\n", event_struct->EventCode, event_struct->CommandKey);
			if (!strcmp(event_struct->EventCode, event_code)) {
				CMS_LOG(LL_ERROR, "del obj, %s", objPathName);
				cmsXmlDelObjByPathName(xmlShmCb, objPathName);
			}
		}
	}
	cmsXmlSave(xmlShmCb);	
}
 
int EventStruct_AddIndex(cmsXmlCb_t *xmlShmCb){
	int index=0;
	uint64_t objIA;
	int addindex=-1;
	void *object = NULL;
	int maxnumber=OID_InternetGatewayDevice_EventStruct_i;
	if(xmlShmCb==NULL)
		return -1;
	CMS_LOG(LL_ERROR, "Enter EventStruct_AddIndex .\n");
	for(index=0;index<maxnumber;index++){
		objIA = cmsXmlConstructIAValue(1, "%d",(index+1));
		object= cmsXml_GetObjectByOID(xmlShmCb, OID_InternetGatewayDevice_EventStruct_i,objIA,NULL_IF_NOT_EXISTED);
		if(object==NULL){
			addindex=index+1;
			break;
		}
	}
	
	return addindex;
}

int cms_cwmpAddEventtoXml(
	cmsXmlCb_t *xmlShmCb,
	char *event_code)

{
	CMS_LOG(LL_ERROR, "Enter cms_cwmpAddEventtoXml .\n");
	uint8_t entry_enable=0;
	int oper_oid=OID_InternetGatewayDevice_EventStruct_i;
	int index=0;
	char tmp_str[128]={0};
	cmsObj_InternetGatewayDevice_EventStruct_i_t EventStruct_entry;
	CMS_LOG(LL_ERROR, "Enter cms_cwmpAddEventtoXml.\n");
	if(xmlShmCb==NULL)
		return -1;
	index=EventStruct_AddIndex(xmlShmCb);
	paraValueSettingList_t *paralist = newParameterList();
	CMS_LOG(LL_ERROR, "event_code=%s\n", event_code);
	setParameterToList(paralist, "EventCode", PARAMETER_TYPE_STRING, event_code);
	setParameterToList(paralist, "CommandKey", PARAMETER_TYPE_STRING, "test");
	cmsXmlAddObjByOIDWithParaList(xmlShmCb, oper_oid,cmsXmlConstructIAValue(1,"%d",index), paralist);
	freeParameterList(paralist);	
	cmsXmlSave(xmlShmCb);			
	return index;

}
#endif

/*
	Description: 
		cwmp add new object instance. 
	Parameters:
 		xmlShmCb --  xml share memory block. 
 		objPath  --  object path, end must with ".". Such as:
 					  InternetGateWay.testObj., add child object of 
 					  testObj.
 		indexNum --  new object instance index.
	return:										
		CMS_OK   -- success	
		CWMP_ERROR   -- fail
		For CWMP RPC AddObject.
*/
int	cmsXml_cwmpAddObject(
	cmsXmlCb_t *xmlShmCb,
	char *objPath, 
	int *indexNum,
	char *parameterKey)
{
	void *object = NULL;
	char objectPath[256] = {0};
	char parameterName[128] = {0};
	int maxNodeCount = 0;			//all support max index node
	uint32_t maxChildNum = 0;    	//current index node support max
	cmsoffset_t objOff;
	int i = 0;
	int ret = -1;
	
	if((xmlShmCb == NULL) || (objPath == NULL)){
		CMS_LOG(LL_ERROR, "xmlshmCb or objPara list is NULL.\n");
		return CWMP_ERROR_INVALID_ARG;
	}

	/*set parameterKey*/
	if(parameterKey != NULL){
		if(strlen(parameterKey) > 32){
			CMS_LOG(LL_ERROR, "size of parameterkey exceeds the limit 32.\n");
			return CWMP_ERROR_INVALID_ARG;
		}
		
		object = cmsXml_GetObjectByName(xmlShmCb, "InternetGatewayDevice.ManagementServer", NULL_IF_NOT_EXISTED);
		if(object){
			objOff = cmsXmlGetPtrOffset(xmlShmCb, object);
			
			paraValueSettingList_t *paralist = newParameterList();
			
			setParameterToList(paralist, "ParameterKey", PARAMETER_TYPE_STRING, parameterKey);
			ret = cmsXmlSetParameterByParaList(xmlShmCb,objOff,paralist);
			if(ret == -1){
				CMS_LOG(LL_ERROR, "set ParameterKey fail.\n");
				return CWMP_ERROR_INTERNAL ;
			}
			freeParameterList(paralist);
		}else{
			CMS_LOG(LL_ERROR, "get ManagementServer fail.\n");
			return CWMP_ERROR_INTERNAL ;
		}
	}

	/*check object is correct, and parse objPath*/
	ret = isObjectOrParameter(objPath, objectPath, parameterName);
	if(ret == -1){
		CMS_LOG(LL_ERROR, "parse object+parameter fail.\n");
		return CWMP_ERROR_INTERNAL ;
	}else if(ret == 1){
		CMS_LOG(LL_ERROR, "input objPath is object+parameter, only need object+'.' .\n");
		return CWMP_ERROR_INVALID_ARG;
	}else{
		CMS_LOG(LL_SPEW, "ret %d, correct object path input, %s.\n", ret, objectPath);
	}

	/*get support max child*/
	cReplace(objectPath, ".", "_");
	strcat(objectPath, "_i");
	maxNodeCount = sizeof(ObjCountTable)/sizeof(ObjCountTable[0]);

	for(i = 0; i < maxNodeCount; i++){
		if(!strcmp(objectPath, ObjCountTable[i].objBuf)){
			maxChildNum = ObjCountTable[i].count;
			break;
		}	
	}
	printf("path is %s, count is %d\n", objPath, maxChildNum);

	if(maxChildNum == 0){
		CMS_LOG(LL_ERROR, "get max num fail, object path may be not index node.\n");
		return CWMP_ERROR_INVALID_ARG;
	}
	
	/*add new instance*/
	for(i = 1; i <= maxChildNum; i++){
		memset(objectPath, 0, 256);
		sprintf(objectPath, "%s%d", objPath, i);

		object = cmsXml_GetObjectByName(xmlShmCb, objectPath, NULL_IF_NOT_EXISTED);
		if(object == NULL){
			cmsXml_addObjectByPathNameIndirect(xmlShmCb, objectPath, 0, NULL);
			*indexNum = i;
			printf("add object index is %d\n", i);
			return CWMP_OK;
		}
	}
	
	return CWMP_ERROR_RES_LEEK;
}


/*
	Description: 
		cwmp del object instance. 
	Parameters:
 		xmlShmCb --  xml share memory block. 
 		objPath  --  object path, end must with "child num". Such as:
 					  InternetGateWay.testObj.2
	return:										
		CMS_OK   -- success	
		CWMP_ERROR   -- fail
		For CWMP RPC DeleteObject.
*/
int	cmsXml_cwmpDelObject(
	cmsXmlCb_t *xmlShmCb, 
	char *objPath,
	char *parameterKey)
{
	void *object = NULL;
	char objectPath[256] = {0};
	char parameterName[128] = {0};
	int maxNodeCount = 0;			//all support max index node
	uint32_t maxChildNum = 0;    	//current index node support max
	cmsoffset_t objOff;
	int i = 0;
	int ret = -1;
	
	if((xmlShmCb == NULL) || (objPath == NULL)){
		CMS_LOG(LL_ERROR, "xmlshmCb or objPara list is NULL.\n");
		return CWMP_ERROR_INVALID_ARG;
	}

	/*set parameterKey*/
	if(parameterKey != NULL){
		if(strlen(parameterKey) > 32){
			CMS_LOG(LL_ERROR, "size of parameterkey exceeds the limit 32.\n");
			return CWMP_ERROR_INVALID_ARG;
		}
		
		object = cmsXml_GetObjectByName(xmlShmCb, "InternetGatewayDevice.ManagementServer", NULL_IF_NOT_EXISTED);
		if(object){
			objOff = cmsXmlGetPtrOffset(xmlShmCb, object);
			
			paraValueSettingList_t *paralist = newParameterList();
			
			setParameterToList(paralist, "ParameterKey", PARAMETER_TYPE_STRING, parameterKey);
			ret = cmsXmlSetParameterByParaList(xmlShmCb,objOff,paralist);
			if(ret == -1){
				CMS_LOG(LL_ERROR, "set ParameterKey fail.\n");
				return CWMP_ERROR_INTERNAL ;
			}
			freeParameterList(paralist);
		}else{
			CMS_LOG(LL_ERROR, "get ManagementServer fail.\n");
			return CWMP_ERROR_INTERNAL ;
		}
	}
	
	/*check object is correct, and parse objPath*/
	ret = isObjectOrParameter(objPath, objectPath, parameterName);
	if(ret == -1){
		CMS_LOG(LL_ERROR, "parse object+parameter fail.\n");
		return CWMP_ERROR_INTERNAL ;
	}else if(ret == 1){
		CMS_LOG(LL_ERROR, "input objPath is object+paramter, only need object+i.\n");
		return CWMP_ERROR_INVALID_ARG;
	}else{
		CMS_LOG(LL_SPEW, "ret %d, correct object path input, objpath %s, index is %d.\n", 
			ret, objectPath, atoi(parameterName));
	}

	/*get support max child*/
	cReplace(objectPath, ".", "_");
	strcat(objectPath, "_i");
	maxNodeCount = sizeof(ObjCountTable)/sizeof(ObjCountTable[0]);

	for(i = 0; i < maxNodeCount; i++){
		if(!strcmp(objectPath, ObjCountTable[i].objBuf)){
			maxChildNum = ObjCountTable[i].count;
			break;
		}	
	}
	printf("path is %s, count is %d\n", objectPath, maxChildNum);

	if(maxChildNum < atoi(parameterName)){
		CMS_LOG(LL_ERROR, "child num(%d) is larger than max(%d), or error path name.\n",
			maxChildNum, atoi(parameterName));
		return CWMP_ERROR_INVALID_ARG;
	}
	
	/*del instance*/
	object = cmsXml_GetObjectByName(xmlShmCb, objPath, NULL_IF_NOT_EXISTED);
	if(object != NULL){
		if(cmsXmlDelObjByPathName(xmlShmCb, objPath) != -1)
			return CWMP_OK;
		else
			return CWMP_ERROR_INVALID_ARG;
	}else{
		CMS_LOG(LL_ERROR, "the object(%s) need del is not exist.\n", objPath);
		return CWMP_ERROR_INVALID_ARG;
	}
	
	return CWMP_OK;
}

static int setNotifyAttr(
	cmsXmlCb_t *xmlShmCb,
	char *objName,
	char *parameterName,
	int notifyType)
{
	void *object = NULL;
	void **parameterList = NULL;
	uint32_t objOff = 0;
	uint32_t notifyAttr = 0;
	uint32_t paramAttr = 0;
	int unsupportActiveFlag = 0;
	int i = 0;

	if(objName == NULL)
		return -1;

	if(parameterName == NULL){	
		parameterList = cmsXml_GetParameterNameByObjectName(xmlShmCb,objName);
		if(parameterList != NULL){
			object = cmsXml_GetObjectByName(xmlShmCb, objName, 1);
			if(object){
				objOff = cmsXmlGetPtrOffset(xmlShmCb, object);
				
				for(i = 0; i < xmlShmCb->meta_count; i++){
					if(*(parameterList + i) != NULL){
						paramAttr = cmsXml_getParameterAttr(xmlShmCb,objOff, *(parameterList + i));
						if(!(((paramAttr & PARAMETER_ATTR_ACTIVE_UNSUPPORT) == PARAMETER_ATTR_ACTIVE_UNSUPPORT) &&
							(notifyType == 2))){
							notifyAttr = 0;
							notifyAttr |= PARAMETER_ATTR_NOTIFY;
							cmsXmlSetParameterAttr(xmlShmCb,objOff, *(parameterList + i),notifyAttr,PARAMETER_ATTR_INACTIVE);

							notifyAttr = 0;
							if(notifyType == 2)
								notifyAttr |= PARAMETER_ATTR_ACTIVENOTIFY;
							else if(notifyType == 1)
								notifyAttr |= PARAMETER_ATTR_PASSIVENOTIFY;

							cmsXmlSetParameterAttr(xmlShmCb,objOff, *(parameterList + i),notifyAttr,PARAMETER_ATTR_ACTIVE);
						}else{
							unsupportActiveFlag = 1;
						}
					}
				}
			}

			cmsXml_freeParameterNameBuffer(parameterList);
		}else{
			CMS_LOG(LL_ERROR,"get object parametername fail.\n");
			return -1;
		}
	}else{
		
		object = cmsXml_GetObjectByName(xmlShmCb, objName, 1);
		if(object){
			objOff = cmsXmlGetPtrOffset(xmlShmCb, object);
			paramAttr = cmsXml_getParameterAttr(xmlShmCb,objOff, parameterName);
			if(!(((paramAttr & PARAMETER_ATTR_ACTIVE_UNSUPPORT) == PARAMETER_ATTR_ACTIVE_UNSUPPORT) &&
				(notifyType == 2))){
				notifyAttr = 0;
				notifyAttr |= PARAMETER_ATTR_NOTIFY;
				cmsXmlSetParameterAttr(xmlShmCb,objOff, parameterName,notifyAttr,PARAMETER_ATTR_INACTIVE);

				notifyAttr = 0;
				if(notifyType == 2)
					notifyAttr |= PARAMETER_ATTR_ACTIVENOTIFY;
				else if(notifyType == 1)
					notifyAttr |= PARAMETER_ATTR_PASSIVENOTIFY;
							
				cmsXmlSetParameterAttr(xmlShmCb,objOff, parameterName,notifyAttr,PARAMETER_ATTR_ACTIVE);
			}else{
				CMS_LOG(LL_ERROR,"set parameter %s noitify attr fail, this param active notify attr is unsupport!!!\n", parameterName);
				return CWMP_ERROR_NOTIFY_UNSUPPORT;
			}
		}else{
			CMS_LOG(LL_ERROR,"get object %s fail.\n", objName);
			return -1;
		}
	}

	if(unsupportActiveFlag == 1)
		return CWMP_ERROR_NOTIFY_UNSUPPORT;
	
	return 0;
}

/*
	Description: 
		cwmp set parameter notify attr. 
	Parameters:
 		xmlShmCb --  xml share memory block. 
 		pathName  --  object path + parameter name or NULL
 		notifyType --  notifyType
 		support 0--off, 2--active, 1--passive
	return:										
		CMS_OK   -- success	
		CWMP_ERROR   -- fail
		For CWMP RPC SetParameterAttributes.
*/
int cmsXml_cwmpSetParameterNotifyAttr(
	cmsXmlCb_t *xmlShmCb,
	char *pathName, 
	int notifyType)
{
	CMS_LOG(LL_SPEW, "Extrance\n");
	//objectList_t *pCurObj = NULL, *objChildList = NULL;
	//char *objPathName = NULL;
	void *object = NULL;
	char objName[256] = {0};
	char paraName[64] = {0};
	cmsoffset_t objOff = 0;
	int ret = -1;
	int notifyRetCode = -1;
	
	if((xmlShmCb == NULL) || (pathName == NULL)){
		CMS_LOG(LL_ERROR,"func parameter is NULL.\n");
		return CWMP_ERROR_INVALID_ARG;
	}

	if((notifyType < 0) || (notifyType > 2)){
		CMS_LOG(LL_ERROR,"cwmp notify attr is error, %d.\n", notifyType);
		return CWMP_ERROR_INVALID_ARG;
	}

	/*
	* if path name is NULL, set all paramter notify attr.
	*/
	/*if(pathName == NULL){
		CMS_LOG(LL_INFO, "set all object paramter notify attr.\n");
		
		object = cmsXml_GetObjectByName(xmlShmCb,"InternetGatewayDevice", NULL_IF_NOT_EXISTED);
		if(object){
			pCurObj = cmsXml_GetObjListByName(xmlShmCb, "InternetGatewayDevice");
			objPathName = cmsXml_GetFullpathByOIDIA(pCurObj->OID, pCurObj->IA);
			setNotifyAttr(xmlShmCb, objPathName, NULL, notifyType);
			free(objPathName);
			
			objChildList = cmsXml_GetFullChildList(xmlShmCb, pCurObj->OID, pCurObj->IA);
			cmsXml_FreeObjList(&pCurObj);
			while(objChildList){
				objPathName = cmsXml_GetFullpathByOIDIA(objChildList->OID, objChildList->IA);
				setNotifyAttr(xmlShmCb, objPathName, NULL, notifyType);
				free(objPathName);
				objChildList = objChildList->next;
			}
			if(objChildList)
				cmsXml_FreeObjList(&objChildList);
		}else{
			CMS_LOG(LL_ERROR, "get object InternetGatewayDevice fail.\n");
			return CWMP_ERROR_INTERNAL;
		}
		
		return CWMP_OK;
	}
	*/

	/*
	*set object paramters notify attr or one paramter notify attr
	*/
	ret = isObjectOrParameter(pathName, objName, paraName);
	if(ret == 0){
		object = cmsXml_GetObjectByName(xmlShmCb, objName, 1);
		if(object){
			notifyRetCode = setNotifyAttr(xmlShmCb, objName, NULL, notifyType);
			if(notifyRetCode == -1){
				CMS_LOG(LL_ERROR, "set parameter fail, pathName %s\n", pathName);
				return CWMP_ERROR_INTERNAL;
			}

			return notifyRetCode;
		}else{
			CMS_LOG(LL_ERROR,"get object %s fail.\n", objName);
			return CWMP_ERROR_INVALID_ARG;
		}
	}else if(ret == 1){
		object = cmsXml_GetObjectByName(xmlShmCb, objName, 1);
		if(object){
			objOff = cmsXmlGetPtrOffset(xmlShmCb, object);
			if(cmsXml_checkParameterExist(xmlShmCb, objOff,  paraName) == -1){
				CMS_LOG(LL_ERROR, "can't found parameter %s in object %s\n", paraName, pathName);
				return CWMP_ERROR_PARA_NAME;
			}
			
			notifyRetCode = setNotifyAttr(xmlShmCb, objName, paraName, notifyType);
			if(notifyRetCode == -1){
				CMS_LOG(LL_ERROR, "set parameter fail, pathName %s\n", pathName);
				return CWMP_ERROR_INTERNAL;
			}

			return notifyRetCode;
		}else{
			CMS_LOG(LL_ERROR,"get object %s fail.\n", objName);
			return CWMP_ERROR_INVALID_ARG;
		}
	}else if(ret == -1){
		CMS_LOG(LL_ERROR,"parse pathName %s fail.\n", pathName);
		return CWMP_ERROR_INVALID_ARG;
	}

	CMS_LOG(LL_SPEW, "Exit\n");
	return CWMP_OK;
}

/*
	Description: 
		cwmp set parameter notify attr by objid. 
	Parameters:
 		xmlShmCb --  xml share memory block. 
 		objID -- orginal object offset
 		objIA -- cur obj instance array of depth
 		notifyType --  notifyType
 		(support 0--off, 2--active, 1--passive)
	return:										
		CWMP_OK   -- success	
		CWMP_ERROR   -- fail
		For CWMP RPC SetParameterAttributes.
*/
int cmsXml_cwmpSetParameterNotifyAttrByOID(
	cmsXmlCb_t *xmlShmCb,
	uint32_t objID,
	uint64_t objIA,
	char *paramName,
	int notifyType)
{
	CMS_LOG(LL_SPEW, "Extrance\n");
	void *object = NULL;
	char *objName = NULL;
	cmsoffset_t objOff = 0;
	int notifyRetCode = -1;
	
	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR,"xmlShmCb is NULL.\n");
		return CWMP_ERROR_INVALID_ARG;
	}

	if((notifyType < 0) || (notifyType > 2)){
		CMS_LOG(LL_ERROR,"cwmp notify attr is error, %d.\n", notifyType);
		return CWMP_ERROR_INVALID_ARG;
	}

	object =  cmsXml_GetObjectByOID(xmlShmCb, objID, objIA, NULL_IF_NOT_EXISTED);
	if(object == NULL){
		CMS_LOG(LL_ERROR,"get object(%d, %"PRIx64") fail.\n", objID, objIA);
		return CWMP_ERROR_INVALID_ARG;
	}

	objName = cmsXml_GetFullpathByOIDIA(objID, objIA);
	if(objName == NULL){
		CMS_LOG(LL_ERROR,"get object name(%d, %"PRIx64") fail.\n", objID, objIA);
		return CWMP_ERROR_INVALID_ARG;
	}

	/*
	*set object paramters notify attr or one paramter notify attr
	*/
	if(paramName == NULL){
		notifyRetCode = setNotifyAttr(xmlShmCb, objName, NULL, notifyType);
		if(notifyRetCode == -1){
			CMS_LOG(LL_ERROR, "set parameter fail, pathName %s\n", objName);
			notifyRetCode = CWMP_ERROR_INTERNAL;
		}
	}else{
		objOff = cmsXmlGetPtrOffset(xmlShmCb, object);
		if(cmsXml_checkParameterExist(xmlShmCb, objOff,  paramName) == -1){
			CMS_LOG(LL_ERROR, "can't found parameter %s in object %s\n", paramName, objName);
			cmsXml_freeFullPathBuffer((void *)&objName);
			return CWMP_ERROR_PARA_NAME; 
		}
		
		notifyRetCode = setNotifyAttr(xmlShmCb, objName, paramName, notifyType);
		if(notifyRetCode == -1){
			CMS_LOG(LL_ERROR, "set parameter fail, pathName %s, paramName %s\n", objName, paramName);
			notifyRetCode =  CWMP_ERROR_INTERNAL;
		}
	}

	cmsXml_freeFullPathBuffer((void *)&objName);
	CMS_LOG(LL_SPEW, "Exit\n");
	
	return notifyRetCode;
}


static int getNotifyAttr(
	cmsXmlCb_t *xmlShmCb,
	char *objName,
	char *parameterName,
	cwmp_getParaAttrList_t **paraAttrList)
{
	void *object = NULL;
	void **parameterList = NULL;
	cwmp_getParaAttrList_t *curParaAttr = NULL;
	cmsoffset_t objOff = 0;
	int attr = 0;
	int notifyAttr = 0;
	int i = 0;

	if(objName == NULL)
		return -1;

	if(parameterName == NULL){
		parameterList = cmsXml_GetParameterNameByObjectName(xmlShmCb,objName);
		if(parameterList != NULL){
			object = cmsXmlGetObjectByName(xmlShmCb, objName);
			if(object){
				objOff = cmsXmlGetPtrOffset(xmlShmCb, object);

				for(i = 0; i < xmlShmCb->meta_count; i++){
					if(*(parameterList + i) != NULL){
						attr = cmsXml_getParameterAttr(xmlShmCb,objOff, *(parameterList + i));
						CMS_LOG(LL_SPEW, "indirect get attr is %d.\n", attr);
						
						if((attr & PARAMETER_ATTR_ACTIVENOTIFY) == PARAMETER_ATTR_ACTIVENOTIFY)
							notifyAttr = 2;
						else if((attr & PARAMETER_ATTR_PASSIVENOTIFY) == PARAMETER_ATTR_PASSIVENOTIFY)
							notifyAttr = 1;
						else
							notifyAttr = 0;

						if((*paraAttrList) == NULL){
							*paraAttrList = (cwmp_getParaAttrList_t *)calloc(1, sizeof(cwmp_getParaAttrList_t));
							//sprintf((*paraAttrList)->parameterName, "%s.%s", objName, (char *)(*(parameterList + i)));
							sprintf((*paraAttrList)->parameterName, "%s", (char *)(*(parameterList + i)));
							(*paraAttrList)->notfiyType = notifyAttr;
						}else{
							curParaAttr= (cwmp_getParaAttrList_t *)calloc(1, sizeof(cwmp_getParaAttrList_t));
							//sprintf(curParaAttr->parameterName, "%s.%s", objName, (char *)(*(parameterList + i)));
							sprintf(curParaAttr->parameterName, "%s", (char *)(*(parameterList + i)));
							curParaAttr->notfiyType = notifyAttr;
							INSERT_NODE((*paraAttrList),curParaAttr);
						}
					}
				}
			}
			cmsXml_freeParameterNameBuffer(parameterList);
		}else{
			CMS_LOG(LL_ERROR,"get object parametername fail.\n");
			return -1 ;
		}
	}else{
		object = cmsXmlGetObjectByName(xmlShmCb, objName);
		if(object){
			objOff = cmsXmlGetPtrOffset(xmlShmCb, object);
			attr = cmsXml_getParameterAttr(xmlShmCb,objOff, parameterName);
	
			if((attr & PARAMETER_ATTR_ACTIVENOTIFY) == PARAMETER_ATTR_ACTIVENOTIFY)
				notifyAttr = 2;
			else if((attr & PARAMETER_ATTR_PASSIVENOTIFY) == PARAMETER_ATTR_PASSIVENOTIFY)
				notifyAttr = 1;
			else
				notifyAttr = 0;

			*paraAttrList = (cwmp_getParaAttrList_t *)calloc(1, sizeof(cwmp_getParaAttrList_t));
			//sprintf((*paraAttrList)->parameterName, "%s.%s", objName, parameterName);
			sprintf((*paraAttrList)->parameterName, "%s", parameterName);
			(*paraAttrList)->notfiyType = notifyAttr;
		}else{
			CMS_LOG(LL_ERROR, "get object %s fail.\n", objName);
			return -1;
		}
	}

	return 0;
}

/*
	Description: 
		cwmp get parameter notify attr by objid. 
	Parameters:
 		xmlShmCb --  xml share memory block. 
		objID -- orginal object offset
		objIA -- cur obj instance array of depth
		paraAttrList -- parameter notify attr list
 		
	return:										
		notfiy attr list  -- success	
		NULL   -- fail
		For CWMP RPC GetParameterAttributes.
*/
int cmsXml_cwmpGetParameterNotifyAttrByOID(
	cmsXmlCb_t *xmlShmCb, 
	uint32_t objID,
	uint64_t objIA,
	char *paramName,
	cwmp_getParaAttrList_t **paraAttrList)
{
	CMS_LOG(LL_SPEW, "Extrance\n");
	void *object = NULL;
	char *objName = NULL;
	int notifyRetCode = -1;
	cmsoffset_t objOff = 0;
	
	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR,"xmlShmCb is NULL.\n");
		return CWMP_ERROR_INVALID_ARG;
	}

	object =  cmsXml_GetObjectByOID(xmlShmCb, objID, objIA, NULL_IF_NOT_EXISTED);
	if(object == NULL){
		CMS_LOG(LL_ERROR,"get object(%d, %"PRIx64") fail.\n", objID, objIA);
		return CWMP_ERROR_INVALID_ARG;
	}

	objName = cmsXml_GetFullpathByOIDIA(objID, objIA);
	if(objName == NULL){
		CMS_LOG(LL_ERROR,"get object name(%d, %"PRIx64") fail.\n", objID, objIA);
		return CWMP_ERROR_INVALID_ARG;
	}

	*paraAttrList = NULL;

	/*
	* get object paramters notify attr or one paramter notify attr.
	*/
	if(paramName == NULL){
		notifyRetCode = getNotifyAttr(xmlShmCb, objName, NULL, paraAttrList);
		if(notifyRetCode == -1){
			CMS_LOG(LL_ERROR, "get parameter notify fail, pathName %s\n", objName);
			notifyRetCode = CWMP_ERROR_INTERNAL;
		}
	}else{
		objOff = cmsXmlGetPtrOffset(xmlShmCb, object);
		if(cmsXml_checkParameterExist(xmlShmCb, objOff,  paramName) == -1){
			CMS_LOG(LL_ERROR, "can't found parameter %s in object %s\n", paramName, objName);
			cmsXml_freeFullPathBuffer((void *)&objName);
			return CWMP_ERROR_PARA_NAME; 
		}
		
		notifyRetCode = getNotifyAttr(xmlShmCb, objName, paramName, paraAttrList);
		if(notifyRetCode == -1){
			CMS_LOG(LL_ERROR, "get parameter notify fail, pathName %s\n", objName);
			notifyRetCode = CWMP_ERROR_INTERNAL;
		}
	}

	cmsXml_freeFullPathBuffer((void *)&objName);
	CMS_LOG(LL_SPEW, "Exit\n");
	
	return notifyRetCode;
}

/*
	Description: 
		cwmp get parameter notify attr. 
	Parameters:
 		xmlShmCb --  xml share memory block. 
 		pathName  --  object path + parameter name or NULL
	return:										
		notfiy attr list   -- success	
		NULL   -- fail
		For CWMP RPC GetParameterAttributes.
*/
int cmsXml_cwmpGetParameterNotifyAttr(
	cmsXmlCb_t *xmlShmCb, 
	char *pathName,
	cwmp_getParaAttrList_t **paraAttrList)
{
	CMS_LOG(LL_SPEW, "Extrance\n");
//	objectList_t *pCurObj = NULL, *objChildList = NULL;
//	char *objPathName = NULL;
	void *object = NULL;
	char objName[256] = {0};
	char paraName[64] = {0};
	int notifyRetCode = -1;
	cmsoffset_t objOff = 0;
	int ret = -1;

	
	if((xmlShmCb == NULL) || (pathName == NULL)){
		CMS_LOG(LL_ERROR,"func parameter is NULL.\n");
		return CWMP_ERROR_INVALID_ARG;
	}

	*paraAttrList = NULL;

	/*
	* if path name is NULL, get all paramter notify attr.
	*/
	/*if(pathName == NULL){
		CMS_LOG(LL_INFO, "get all object paramter attr.\n");
		object = cmsXml_GetObjectByName(xmlShmCb,"InternetGatewayDevice", NULL_IF_NOT_EXISTED);
		if(object){
			pCurObj = cmsXml_GetObjListByName(xmlShmCb, "InternetGatewayDevice");
			objPathName = cmsXml_GetFullpathByOIDIA(pCurObj->OID, pCurObj->IA);
			getNotifyAttr(xmlShmCb, objPathName, NULL, paraAttrList);
			free(objPathName);

			objChildList = cmsXml_GetFullChildList(xmlShmCb, pCurObj->OID, pCurObj->IA);
			cmsXml_FreeObjList(&pCurObj);
			while(objChildList){
				objPathName = cmsXml_GetFullpathByOIDIA(objChildList->OID, objChildList->IA);
				getNotifyAttr(xmlShmCb, objPathName, NULL, paraAttrList);
				free(objPathName);
				objChildList = objChildList->next;
			}
			if(objChildList)
				cmsXml_FreeObjList(&objChildList);
		}else{
			CMS_LOG(LL_ERROR, "get object InternetGatewayDevice fail.\n");
			return CWMP_ERROR_INTERNAL;
		}
		
		return CWMP_OK;
	}
	*/
	/*
	* get object paramters notify attr or one paramter notify attr.
	*/
	ret = isObjectOrParameter(pathName, objName, paraName);
	if(ret == 0){
		object = cmsXmlGetObjectByName(xmlShmCb, objName);
		if(object){
			notifyRetCode = getNotifyAttr(xmlShmCb, objName, NULL, paraAttrList);
			if(notifyRetCode == -1){
				CMS_LOG(LL_ERROR, "get parameter notify fail, pathName %s\n", pathName);
				return CWMP_ERROR_INTERNAL;
			}
		}else{
			CMS_LOG(LL_ERROR,"get object %s fail.\n", objName);
			return CWMP_ERROR_INVALID_ARG;
		}
	}else if(ret == 1){
		object = cmsXml_GetObjectByName(xmlShmCb, objName, 1);
		if(object){
			objOff = cmsXmlGetPtrOffset(xmlShmCb, object);
			if(cmsXml_checkParameterExist(xmlShmCb, objOff, paraName) == -1){
				CMS_LOG(LL_ERROR, "can't found parameter %s in object %s\n", paraName, pathName);
				return CWMP_ERROR_PARA_NAME;
			}
			
			notifyRetCode = getNotifyAttr(xmlShmCb, objName, paraName, paraAttrList);
			if(notifyRetCode == -1){
				CMS_LOG(LL_ERROR, "get parameter notify fail, pathName %s\n", pathName);
				return CWMP_ERROR_INTERNAL;
			}
		}else{
			CMS_LOG(LL_ERROR,"get object %s fail.\n", objName);
			return CWMP_ERROR_INVALID_ARG;
		}
	}else if(ret == -1){
		CMS_LOG(LL_ERROR,"parse pathName %s fail.\n", pathName);
		return CWMP_ERROR_INVALID_ARG;
	}

	CMS_LOG(LL_SPEW, "Exit\n");
	return CWMP_OK;
}


int cmsXml_cwmpFreeParaNotifyAttrList(cwmp_getParaAttrList_t *paraAttrList)
{
	cwmp_getParaAttrList_t *curObjPara = NULL, *tmpObjPara = NULL;

	if(paraAttrList == NULL){
		CMS_LOG(LL_ERROR, "objPara list is NULL.\n");
		return -1;
	}

	curObjPara = paraAttrList;
	while(curObjPara){
		tmpObjPara = curObjPara;
		curObjPara = curObjPara->next;
		
		DELETE_NODE(paraAttrList,tmpObjPara);
	}

	return 0;
}

cms_paramChgList_t *cmsXml_getChgParamList(cmsXmlCb_t *xmlShmCb, void *pNewObj, void *pOldObj)
{
	cms_paramChgList_t *pHeadList = NULL, *pCurList = NULL;
	cmsoffset_t metaOffset, nodeOffset;
	char *metaAddr, *nodeAddr;
	objectNode_t	*node;
	uint16_t meta_count;
	void *meta_ptr, *tmpObj = NULL;
	uint8_t meta_len = 0;
	uint32_t type = 0;
	uint32_t width = 0;
	uint32_t dataSize = 0;
	int defaultFlag = 0;
	cmsoffset_t attrOffset = 0;
	uint32_t padding = 0;
	int nonConfParamFlag = 0; 
	
	if(xmlShmCb == NULL ) {
		CMS_LOG(LL_ERROR, "xml shm is NULL.\n");
		return NULL;
	}
	
	XML_LOCK(&xmlShmCb->cmsMutex->lock);

	if(pNewObj == NULL || pOldObj == NULL){
		CMS_LOG(LL_ERROR, "new obj or old obj is NULL.\n");
		XML_UNLOCK(&xmlShmCb->cmsMutex->lock);
		return NULL;
	}

	tmpObj = calloc(1, xmlShmCb->objectSize);
	if(tmpObj)
		memcpy(tmpObj, pNewObj , xmlShmCb->objectSize);
	else{
		CMS_LOG(LL_ERROR, "calloc fail.\n");
		XML_UNLOCK(&xmlShmCb->cmsMutex->lock);
		return NULL;
	}
		
	/*use object to find the meta data*/
	metaAddr = pNewObj -sizeof(cmsoffset_t);
	metaOffset = *((cmsoffset_t *)metaAddr);
	
	/*get meta ptr*/
	meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, metaOffset);	

	/*use object to find the object node*/
	nodeAddr = pNewObj -sizeof(cmsoffset_t)*2;
	nodeOffset = *((cmsoffset_t *)nodeAddr);
	node = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, nodeOffset);

	meta_count = node->meta_count;
	while(meta_count){

		meta_len = *((uint8_t *)meta_ptr);
		if ((meta_len != PADDING_META_LEN)){		
			type = *((uint32_t *)(meta_ptr + meta_len - sizeof(uint32_t)));
			if ((type & PARAMETER_TYPE_STRING) == PARAMETER_TYPE_STRING){
				type = PARAMETER_TYPE_STRING;
			}

			switch (type){
			case PARAMETER_TYPE_SINT7:
			case PARAMETER_TYPE_UINT8:
			case PARAMETER_TYPE_BOOLEAN:
				width = 1;
				break;
			case PARAMETER_TYPE_SINT15:
			case PARAMETER_TYPE_UINT16:
				width = 2;
				break;
			case PARAMETER_TYPE_SINT31:
			case PARAMETER_TYPE_UINT32:
				width = 4;			
				break;
			case PARAMETER_TYPE_SINT63:
			case PARAMETER_TYPE_UINT64:
				width = 8;		
				break;
			case PARAMETER_TYPE_MAC:
				width = 6;
				break;
			case PARAMETER_TYPE_IPV4:
				width = 4;
				break;
			case PARAMETER_TYPE_IPV6:
				width = 16;
				break;
			case PARAMETER_TYPE_DATETIME:
				width = 27;
				break;
			case PARAMETER_TYPE_STRING:
				width = *(uint32_t *)(meta_ptr + meta_len - sizeof(uint32_t)) & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);		
				break;
			}

			attrOffset = *((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(uint32_t)+sizeof(cmsoffset_t))));
			defaultFlag = 0;
			if ((*((uint32_t *)(pNewObj + NTOHDL(attrOffset))) & PARAMETER_ATTR_DEFAULTVALUE) == PARAMETER_ATTR_DEFAULTVALUE){
				defaultFlag = 1;
			}

			if ((nonConfParamFlag == 0) && ((*((uint32_t *)(pNewObj + NTOHDL(attrOffset))) & PARAMETER_ATTR_CONFIG) != PARAMETER_ATTR_CONFIG)){
				padding = dataSize%BYTE_ALIGNS;
				if (padding != 0){
					padding = BYTE_ALIGNS - padding;
				}
				dataSize += padding;
				nonConfParamFlag = 1;
			}

			if(memcmp(pOldObj+dataSize, tmpObj+dataSize, width) != 0){
				CMS_LOG(LL_FLOOD, "param name %s, type 0x%x, datasize %d width %d, isDefault %d, nonConfFlag %d, changed\n", 
					(char *)(meta_ptr+sizeof(uint8_t)), type,dataSize, width, defaultFlag, nonConfParamFlag);
				if(pHeadList == NULL){
					pHeadList = (cms_paramChgList_t *)calloc(1, sizeof(cms_paramChgList_t));
					if(pHeadList){
						strcpy(pHeadList->paramName, (char *)(meta_ptr+sizeof(uint8_t)));
					}else{	
						CMS_LOG(LL_ERROR, "calloc fail!!!\n");
						free(tmpObj);
						XML_UNLOCK(&xmlShmCb->cmsMutex->lock);
						return NULL;
					}
				}else{
					pCurList = (cms_paramChgList_t *)calloc(1, sizeof(cms_paramChgList_t));
					if(pCurList){
						strcpy(pCurList->paramName, (char *)(meta_ptr+sizeof(uint8_t)));
						INSERT_NODE(pHeadList,pCurList);
					}else{	
						CMS_LOG(LL_ERROR, "calloc fail!!!\n");
						cmsXml_freeChgParamList(pHeadList);
						free(tmpObj);
						XML_UNLOCK(&xmlShmCb->cmsMutex->lock);
						return NULL;
					}
				}
			}else{
				CMS_LOG(LL_FLOOD, "param name %s, type 0x%x, data size %d, width %d, isDefault %d, nonConfFlag %d, no changed\n", 
					(char *)(meta_ptr+sizeof(uint8_t)), type, dataSize, width, defaultFlag, nonConfParamFlag);
			}

			if(defaultFlag == 1)
				dataSize += 2*width;
			else
				dataSize += width;

		}
		meta_ptr = meta_ptr + meta_len;
		meta_count--;
		
	}
	
	free(tmpObj);
	XML_UNLOCK(&xmlShmCb->cmsMutex->lock);

	return pHeadList;
}

void cmsXml_freeChgParamList(cms_paramChgList_t *parameterList)
{
	cms_paramChgList_t *pCurParaList = NULL, *tmpParaList = NULL;

	pCurParaList = parameterList;
	while(pCurParaList){
		tmpParaList = pCurParaList;
		pCurParaList = pCurParaList->next;

		DELETE_NODE(parameterList, tmpParaList);
	}
}

cms_objDbusNotify_t *cmsXml_getChgObjInfo(char *eventContent)
{
	cms_objDbusNotify_t *pHead = NULL;
	uint32_t objId = 0;
	uint64_t objIA = 0;
	int objAction = 0;
	char *ptr = NULL;
	char *savePtr = NULL;
	char *paramList = NULL;

	if(eventContent == NULL)
		return NULL;
	
	pHead = (cms_objDbusNotify_t *)calloc(1, sizeof(cms_objDbusNotify_t));
	if(pHead == NULL){
		printf("dbus notify calloc fail\n");
		return NULL;
	}

	paramList = (char *)calloc(1, strlen(eventContent));
	if(paramList == NULL){
		printf("dbus notify calloc param list fail\n");
		free(pHead);
		return NULL;
	}

	sscanf(eventContent, "%u;%ju;%d;%s", &objId, &objIA, &objAction, paramList);
	pHead->objID = objId;
	pHead->objIA = objIA;
	pHead->objAction = objAction;

	if(strcmp(paramList, "NULL") != 0){//object modify
		if(strstr(paramList, ";") == NULL){//only one parameter modified
			pHead->parameterList = (cms_paramChgList_t *)calloc(1, sizeof(cms_paramChgList_t));
			strcpy(pHead->parameterList->paramName, paramList);	
		}else{//multi param modified
			cms_paramChgList_t *paramHead = NULL, *curParam = NULL;
			ptr = strtok_r(paramList, ";", &savePtr);
			if(ptr == NULL){
				printf("[%s-%d]: parameter name size is NULL!!!\n", __FUNCTION__, __LINE__);		
				goto error;
			}

			while(ptr ){
				if(paramHead == NULL){
					paramHead = (cms_paramChgList_t *)calloc(1, sizeof(cms_paramChgList_t));
					strcpy(paramHead->paramName, ptr);
				}else{
					curParam = (cms_paramChgList_t *)calloc(1, sizeof(cms_paramChgList_t));
					strcpy(curParam->paramName, ptr);
					INSERT_NODE(paramHead, curParam);
				}
				ptr = strtok_r(NULL, ";", &savePtr);
			}

			pHead->parameterList = paramHead;
		}
	}else{//object add or del
		pHead->parameterList = NULL;
	}
	
	free(paramList);
	
	return pHead;

error:
	free(pHead);
	free(paramList);
	return NULL;

}

void cmsXml_freeChgObjInfo(cms_objDbusNotify_t **pObjChg)
{
	cms_paramChgList_t *pCurParam = NULL, *pTmpParam =NULL;
	
	if((*pObjChg) != NULL){
		pCurParam = (*pObjChg)->parameterList;
		
		while(pCurParam){
			pTmpParam = pCurParam;
			pCurParam = pCurParam->next;
			DELETE_NODE((*pObjChg)->parameterList, pTmpParam);
		}

		free(*pObjChg);
		*pObjChg = NULL;
	}
}

cmsBoolean cmsXml_checkParamChg(cms_objDbusNotify_t *pObjChg, char *paramName)
{
	cms_paramChgList_t *pCurParam = NULL;
		
	if(pObjChg == NULL || paramName == NULL){
		printf("func para is NULL\n");
		return FALSE;
	}

	if(pObjChg->parameterList == NULL)
		return FALSE;

	pCurParam = pObjChg->parameterList;
	while(pCurParam){
		if(strcmp(pCurParam->paramName, paramName) == 0){
			return TRUE;
		}
		pCurParam = pCurParam->next;
	}

	return FALSE;
}

cmsBoolean cmsXml_checkobjNeedNotify(cmsXmlCb_t *xmlShmCb, uint32_t objID)
{
	cmsoffset_t metaOffset = 0, nodeOffset = 0;
	char *metaAddr = NULL, *nodeAddr = NULL;
	objectNode_t *node = NULL;
	uint16_t meta_count = 0;
	void *meta_ptr = NULL;
	uint8_t meta_len = 0;
	cmsoffset_t valueOffset = 0;
	void *object = NULL;
	char objPath[64] = {0};
	int i = 0;
	
	if(xmlShmCb == NULL ) {
		CMS_LOG(LL_ERROR, "xml shm is NULL.\n");
		return FALSE;
	}

	for(i = 0; i < InternetGatewayDevice_X_GC_DBUS_i_Max; i++){
		memset(objPath, 0, 64);
		sprintf(objPath, "InternetGatewayDevice.X_GC_DBUS.%d", i+1);
		object = cmsXml_getObjectByPathName(xmlShmCb, objPath);
		if(object == NULL ){
			if(i == 0)
				CMS_LOG(LL_DEBUG, "dbus object is NULL.\n");
			return FALSE;
		}
			
		/*use object to find the meta data*/
		metaAddr = object -sizeof(cmsoffset_t);
		metaOffset = *((cmsoffset_t *)metaAddr);
		
		/*get meta ptr*/
		meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, metaOffset);	

		/*use object to find the object node*/
		nodeAddr = object -sizeof(cmsoffset_t)*2;
		nodeOffset = *((cmsoffset_t *)nodeAddr);
		node = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, nodeOffset);

		meta_count = node->meta_count;
		while(meta_count){

			meta_len = *((uint8_t *)meta_ptr);
			if ((meta_len != PADDING_META_LEN)){
				valueOffset = NTOHDL(*((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(cmsoffset_t)*2+sizeof(uint32_t)))));
				CMS_LOG(LL_SPEW, "dbus object paramName %s, value is %d\n", (char *)(meta_ptr+sizeof(uint8_t)), *((int32_t *)(object+valueOffset)));
				if(*((int32_t *)(object+valueOffset)) == objID){
					return TRUE;
				}
			}
			meta_ptr = meta_ptr + meta_len;
			meta_count--;
		}
	}

	return FALSE;
}



/*************************cwmp api useage demo*********************************/
#if 0
static void usage_print(void)
{
	printf("\n cwmp api test demo useage:\n");
	printf("a: add object -- RPC AddObject\n");
	printf("demo -a objectPath ParametereKey\n");
	printf("\n\r");
	printf("d: delete object -- PRC DelObject\n");
	printf("demo -d objectPath ParametereKey\n");
	printf("\n\r");
	printf("s: set parameter value -- PRC SetParameterValues\n");
	printf("demo -s pathName value type ParametereKey\n");
	printf("\n\r");
	printf("g: get parameter value -- RPC GetParameterValues\n");
	printf("demo -g parameterName\n");
	printf("\n\r");
	printf("p: get parameter name -- RPC GetParameterNames\n");
	printf("demo -p parameterName nextLevel\n");
	printf("\n\r");
	printf("n: set notify attr\n");
	printf("demo -n pathName notifyType\n");
	printf("\n\r");
	printf("f: get notify attr\n");
	printf("demo -f pathName\n");
	printf("\n\r");
}

int main(int argc, char *argv[]){
	cmsXmlCb_t *xmlShmCb= NULL;
	int opt = 0;
	int ret = -1;
	set_log_level(CMS_SAMPLE, LL_ERROR);
	cms_registerModule(CMS_SAMPLE);
	xmlShmCb = XMLSHMINIT();
	
	while((opt = getopt(argc, argv, "a:d:s:g:p:n:f")) != -1){
		switch(opt){
		case 'a':
			/*demo -a objectPath parameterKey
			* for RPC AddObject
			*/
			if(argc != 4){
				usage_print();
				return -1;
			}else{
				printf("input arg %s, %s, %s, %s\n", argv[0], argv[1], argv[2], argv[3]);
			}

			int indexNum = 0;
			ret = cmsXml_cwmpAddObject(xmlShmCb, argv[2], &indexNum,argv[3]);
			printf("add object index num is %d, ret %d\n", indexNum, ret);
			
			break;
		case 'd':
			/*demo -d objectPath parameterKey
			* for RPC DeleteObject
			*/
			if(argc != 4){
				usage_print();
				return -1;
			}else{
				printf("input arg %s, %s, %s, %s\n", argv[0], argv[1], argv[2], argv[3]);
			}

			ret = cmsXml_cwmpDelObject(xmlShmCb, argv[2], argv[3]);
			printf("demo return code is %d\n", ret);
			break;
		case 's':
			/*demo -s parameterPath value type parameterKey
			* for RPC SetParameterValues
			*/
			if(argc != 6){
				usage_print();
				return -1;
			}else{
				printf("input arg %s, %s, %s, %s, %s, %s\n", argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
			}

			ret = cmsXml_cwmpSetParameterValue(xmlShmCb, argv[2], argv[3], atoi(argv[4]), argv[5]);
			printf("demo return code is %d\n", ret);
			break;
		case 'g':
			/*demo -g parameterPath
			* for RPC GetParameterValues
			*/
			if(argc != 3){
				usage_print();
				return -1;
			}else{
				printf("input arg %s, %s, %s\n", argv[0], argv[1], argv[2]);
			}

			paraValueSettingList_t *parameterList = NULL, *curParaList = NULL;

			if(strcmp(argv[2], "NULL") == 0)
				ret = cmsXml_cwmpGetParameterValue(xmlShmCb, NULL, &parameterList);
			else
				ret = cmsXml_cwmpGetParameterValue(xmlShmCb, argv[2], &parameterList);
			if(ret == 0){
				curParaList = parameterList;
				while(curParaList){
					if((curParaList->type == CWMP_PARAM_TYPE_STRING) || (curParaList->type == CWMP_PARAM_TYPE_DATATIME))
						printf("parameter name: %s, type: %d, value %s\n",
						curParaList->parameter, curParaList->type, curParaList->value);
					else if(curParaList->type == CWMP_PARAM_TYPE_INT)
						printf("parameter name: %s, type: %d, value %d\n",
						curParaList->parameter, curParaList->type, *(int32_t *)curParaList->value);
					else if(curParaList->type == CWMP_PARAM_TYPE_UNSINGED_INT)
						printf("parameter name: %s, type: %d, value %u\n",
						curParaList->parameter, curParaList->type, *(uint32_t *)curParaList->value);
					else if(curParaList->type == CWMP_PARAM_TYPE_BOOLEAN)
						printf("parameter name: %s, type: %d, value %d\n",
						curParaList->parameter, curParaList->type, *(uint8_t *)curParaList->value);
					else
						printf("parameter name: %s, type: %d, value %s\n",
						curParaList->parameter, curParaList->type, curParaList->value);
					
					curParaList = curParaList->next;
				}
			}else{
				printf("get parameter value fail, ret %d\n", ret);
			}
			cmsXml_cwmpFreeParameterValue(parameterList);
			printf("demo return code is %d\n", ret);
			break;
		case 'p':
			/*demo -p parameterPath netLevel
			* for RPC GetParameterNames
			*/
			if(argc != 4){
				usage_print();
				return -1;
			}else{
				printf("input arg %s, %s, %s, %s\n", argv[0], argv[1], argv[2], argv[3]);
			}
			cwmp_getObjParaList_t *objParaList = NULL, *curObjParaList = NULL;

			if(strcmp(argv[2], "NULL") == 0)
				 ret= cmsXml_cwmpGetObjParaList(xmlShmCb, NULL, atoi(argv[3]), &objParaList);
			else
				ret = cmsXml_cwmpGetObjParaList(xmlShmCb, argv[2], atoi(argv[3]), &objParaList);
			if(ret == 0){
				curObjParaList = objParaList;
				while(curObjParaList){
					printf("object/parametr name %s, writable %d\n", curObjParaList->parameterPath, curObjParaList->writeable);
					curObjParaList = curObjParaList->next;
				}
			}else{
				printf("get object parameter name fail, ret %d\n", ret);
			}

			cmsXml_cwmpFreeObjParaList(objParaList);
			printf("demo return code is %d\n", ret);
			break;
		case 'n':
			/*demo -n parameterPath notifyType
			* for RPC SetParameterAttributes
			*/
			if(argc != 4){
				usage_print();
				return -1;
			}else{
				printf("input arg %s, %s, %s, %s\n", argv[0], argv[1], argv[2], argv[3]);
			}
			if(strcmp(argv[2], "NULL") == 0)
				ret = cmsXml_cwmpSetParameterNotifyAttr(xmlShmCb, NULL, atoi(argv[3]));
			else
				ret = cmsXml_cwmpSetParameterNotifyAttr(xmlShmCb, argv[2], atoi(argv[3]));
			printf("demo return code is %d\n", ret);
			break;
		case 'f':
			/*demo -f parameterPath
			* for RPC GetParameterAttributes
			*/
			if(argc != 3){
				usage_print();
				return -1;
			}else{
				printf("input arg %s, %s, %s\n", argv[0], argv[1], argv[2]);
			}

			cwmp_getParaAttrList_t *attrList = NULL, *curAttrList = NULL;

			if(strcmp(argv[2], "NULL") == 0)
				ret = cmsXml_cwmpGetParameterNotifyAttr(xmlShmCb, NULL, &attrList);
			else
				ret = cmsXml_cwmpGetParameterNotifyAttr(xmlShmCb, argv[2], &attrList);
			if(ret == CWMP_OK){
				curAttrList = attrList;
				while(curAttrList){
					printf("parameter name %s, notify type %d\n", curAttrList->parameterName, curAttrList->notfiyType);
					curAttrList = curAttrList->next;
				}
			}else{
				printf("get notify attr fail, ret %d\n", ret);
			}
			cmsXml_cwmpFreeParaNotifyAttrList(attrList);
			printf("demo return code is %d\n", ret);
			break;
		default:
			usage_print();
			break;
		}
	}

	XMLSHMDEINIT(xmlShmCb);
	//cms_unregisterModule(CMS_SAMPLE);

	if(argc < 3){
		usage_print();
	}

	return ret;
}
#endif
